day10.闭包函数与装饰器
一.闭包函数
1.闭函数:被封闭起来的函数==>定义在函数内部的函数,特点是只能在函数内调用
2.包函数:该函数引用了一个名字,该名字来自于E这一层
总结:闭包函数指的是定义在函数内部的函数引用了一个来自于外层函数作用域中的名字
#例如wrapper函数
# def outter():
# x = 100
# def wrapper():
# print(x)
3.闭包函数升级:结合函数对象
# def outter():
# x = 100
# def wrapper():
# print(x)
# return wrapper # 千万不要加括号
#
# f = outter()
#
# print(f)
#
# def foo():
# x = 666
# f()
#
# foo()
4.为函数体传参的两种解决方案
方案一:直接以参数的形式传入
# def wrapper(x):
# print(x)
#
# wrapper(100)
方案二:闭包函数方式
# def outter(x):
# # x = 100
# def wrapper():
# print(x)
# return wrapper # 千万不要加括号
#
# f = outter(100)
# f()
二.装饰器
1.什么是装饰器
’装饰’代指为被装饰对象添加新的功能
’器’代指器具/工具
但实现装饰器必须遵循的原则是:开放封闭原则
开放指的是对拓展新功能是开放的,封闭指的则是对修改源代码以及调用方式是封闭的
#综上装饰器指的是我们要创建一个工具,该工具可以在遵循原则1和2的前提下还能为被装饰对象添加新功能
原则1、不修改被装饰对象源代码
原则2、不修改被装饰对象调用方式
2.为什么要用装饰器
软件包含的所有功能的源代码以及调用方式,都应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃,而对于上线后的软件,新需求或者变化又层出不穷,我们必须为程序提供扩展的可能性,这就用到了装饰器。
3.用法
**装饰器的推导**
# 被装饰者:给被装饰者添加新功能
# import time
#
# def index():
# print('from index')
# time.sleep(3)
#
# index() # 方案一:改变被装饰者的源代码
# import time
#
# def index():
# start = time.time()
# print('from index')
# time.sleep(1)
# end = time.time()
# print('run time is %s' %(end - start))
#
# index() # # 方案二:装饰器的功能需要重复编写,代码冗余
# import time
#
# def index():
# print('from index')
# time.sleep(1)
#
# start = time.time()
# index()
# end = time.time()
# print('run time is %s' %(end - start))
#
# start = time.time()
# index()
# end = time.time()
# print('run time is %s' %(end - start))
# # # 方案三:解决方案二的代码冗余问题,但是存在问题-》装饰器的功能写死了,只能装饰index函数
# import time
#
# def index():
# print('from index')
# time.sleep(1)
#
# def wrapper():
# start = time.time()
# index()
# end = time.time()
# print('run time is %s' %(end - start))
#
# wrapper()
# wrapper() # # 方案四:装饰器的功能写活
# import time
#
# def index():
# print('from index')
# time.sleep(1)
#
# def outter(func):
# # func = index
# def wrapper():
# start = time.time()
# func()
# end = time.time()
# print('run time is %s' %(end - start))
# return wrapper
#
# index = outter(index) # index = wrapper的内存地址
# # print(index)
# index() # 方案五:装饰器的功能写活
import time def index():
print('from index')
time.sleep(1) def home(name):
print('welcome %s to home page' % name)
time.sleep(0.5)
return 123 def outter(func):
# func = 最原始那个home的内存地址
def wrapper(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs) # 最原始那个home的内存地址()
end = time.time()
print('run time is %s' % (end - start))
return res
return wrapper home = outter(home) # home = wrapper的内存地址
index = outter(index) # home = wrapper的内存地址 res = home('egon')
print(res) # res = index()
# print(res)
**装饰器语法糖**(简化)
import time def outter(func):
# func = 最原始那个home的内存地址
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs) # 最原始那个home的内存地址()
end = time.time()
print('run time is %s' % (end - start))
return res return wrapper @outter # index = outter(index)
def index():
print('from index')
time.sleep(1) @outter # home = outter(home)
def home(name):
print('welcome %s to home page' % name)
time.sleep(0.5)
return 123 res = home('lzl')
print(res)
**多个装饰器叠加**
# 装饰器模板
# def deco(func):
# def wrapper(*args,**kwargs):
# res = func(*args,**kwargs)
# return res
# return wrapper # 统计时间的装饰器
# import time
#
# def timmer(func):
# def wrapper(*args,**kwargs):
# start = time.time()
# res = func(*args,**kwargs)
# stop = time.time()
# print(stop - start)
# return res
# return wrapper # 认证功能装饰器
# def auth(func):
# def wrapper(*args,**kwargs):
# inp_user = input('Username: ').strip()
# inp_pwd = input('Password: ').strip()
# if inp_user == 'egon' and inp_pwd == '123':
# res = func(*args,**kwargs)
# return res
# else:
# print('登录失败')
# return wrapper
#
# @auth # index = auth(index)
# def index():
# print('from index')
#
# index() """
def deco1(func1): # func1 = wrapper2的内存地址
def wrapper1(*args,**kwargs):
print('===>wrapper1')
res1 = func1(*args,**kwargs)
print('=====>end wrapper1')
return res1
return wrapper1 def deco2(func2): # func2 = wrapper3的内存地址
def wrapper2(*args,**kwargs):
print('===>wrapper2')
res2 = func2(*args,**kwargs)
print('=====>end wrapper2')
return res2
return wrapper2 def deco3(func3): # func3 = 最原始那个index的内存地址
def wrapper3(*args,**kwargs):
print('===>wrapper3')
res3 = func3(*args,**kwargs)
print('=====>end wrapper3')
return res3
return wrapper3 # index = wrapper1的内存地址
@deco1 # deco1(wrapper2的内存地址) ---> wrapper1的内存地址
@deco2 # deco2(wrapper3的内存地址) ---> wrapper2的内存地址
@deco3 # deco3(最原始那个index的内存地址) ---> wrapper3的内存地址
def index():
print('=======>index') index()
""" # print(index) import time def timmer(func):
def wrapper1(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
stop = time.time()
print(stop - start)
return res
return wrapper1 def auth(func):
def wrapper2(*args,**kwargs):
inp_user = input('Username: ').strip()
inp_pwd = input('Password: ').strip()
if inp_user == 'egon' and inp_pwd == '123':
res = func(*args,**kwargs)
return res
else:
print('登录失败')
return wrapper2 @auth
@timmer
def index():
print('====>index')
time.sleep(3)
index()
有参装饰器:
def outter2(mode,yyy):
# mode = 'mysql'
def outter(func): # func = index
def wrapper(*args ,**kwargs):
print(yyy)
inp_user = input('Username: ').strip()
inp_pwd = input('Password: ').strip()
if mode == 'file':
if inp_user == "egon" and inp_pwd == "123":
res = func(*args ,**kwargs)
return res
else:
print('login failed')
elif mode == 'mysql':
print("基于mysql数据库的认证")
elif mode == 'ldap':
print("基于ldap数据库的认证")
else:
print('未知的认证来源')
return wrapper
return outter @outter2('mysql',111) # @outter # index = outter(index) # index = wrapper
def index():
print('from index') @outter2('ldap',222)
def home(name):
print('hello %s' %name)
###functools模块下提供一个装饰器wraps专门用来保留原函数属性####
4.总结
1、无参装饰器模板
# def outter(func):
# def wrapper(*args,**kwargs):
# res = func(*args,**kwargs)
# return res
# return wrapper
#
# @outter
# def index():
# pass
2、有参装饰器模板
def outter2(xxx):
def outter(func):
def wrapper(*args,**kwargs):
xxx
res = func(*args,**kwargs)
return res
return wrapper
return outter @outter2(xxx=111)
def index():
pass
day10.闭包函数与装饰器的更多相关文章
- day11 闭包函数和装饰器
1.函数不是新知识点 主要是学习函数的用法 在面向对象编程中,一切皆对象,函数也不例外 具体的表现 1.函数可以引用 2.函数可以作为函数的参数 3.函数可以作为函数的返回值 4.可以被存储到容器类型 ...
- python基础-闭包函数和装饰器
闭包函数和装饰器 闭包函数 概念:在函数中(嵌套)定义另一个函数时,内部函数引用了外层函数的名字. 特性 闭包函数必须在函数内部定义 闭包函数可引用外层函数的名字 闭包函数是函数嵌套.函数对象.名称空 ...
- Python之函数对象、函数嵌套、名称空间与作用域、闭包函数、装饰器
目录 一 函数对象 二 函数的嵌套 三 名称空间和作用域 四 闭合函数 五 装饰器 一.函数对象 1.函数是第一类对象 #第一类对象的特性:# 可以被引用 # 可以当做参数传递 # 返回值是函数 # ...
- 【Python3的命名空间与作用域,闭包函数,装饰器】
一.命名空间与作用域 命名空间是名字和对象的映射,就像是字典,key是变量名,value是变量的值 1.命名空间的定义 name='egon' #定义变量 def func(): #定义函数 pass ...
- day11_7.11 闭包函数与装饰器
补充: callable 代表可调用的,加括号可以执行.(函数或者类) import this 查看python之禅 一.闭包函数 所谓闭包函数,就是定义在函数内部的函数,也就是函数定义的嵌套.而在 ...
- CSIC_716_20191112【闭包函数和装饰器】
闭包函数 什么是闭包函数:闭包函数是函数嵌套.函数对象.名称空间和作用域的集合体. 闭包函数必须在函数内部定义,闭包函数可以引用外层函数的名字. # _*_ coding: gbk _*_ # @Au ...
- Python--day13(函数嵌套定义,global、nonlocal、闭包函数、装饰器)
今日主要内容 1. 函数的嵌套定义 2. global.nonlocal关键字 3. 闭包及闭包的应用场景 4. 装饰器 1. 函数的嵌套定义 概念:在一个函数的内部定义另一个函数 为什么要有 ...
- python---基础知识回顾(二)(闭包函数和装饰器)
一.闭包函数: 闭包函数: 1.在一个外函数中定义了一个内函数 2.内函数里运用了外函数的临时变量,而不是全局变量 3.并且外函数的返回值是内函数的引用.(函数名,内存块地址,函数名指针..) 正确形 ...
- Python之闭包函数、装饰器
1.闭包函数 #作用域关系在函数定义阶段时就已经固定死了,与调用位置无关 # 即:在任意位置调用函数都需要跑到定义函数时寻找作用域关系 # def f1(): # x=1 # def inner(): ...
随机推荐
- 如何把数据放到C#的心里之 DB2实例
平时偶尔因为工作需要得自己写一些小工具去操作数据库,因为只是需要实现一些小的功能,也不涉及多类型的数据库,也许就是一次性的使用.所以此时那些大而全的数据库操作框架,也就不再那么适合我了.而本篇博文主要 ...
- 使用 Tye 辅助开发 k8s 应用竟如此简单(六)
续上篇,这篇我们来进一步探索 Tye 更多的使用方法.本篇我们将进一步研究 Tye 与分布式应用程序运行时 Dapr 如何碰撞出更精彩的火花. Newbe.Claptrap 是一个用于轻松应对并发问题 ...
- C语言柔性数组和动态数组
[前言]经常看到C语言里的两个数组,总结一下. 一.柔性数组 参考:https://www.cnblogs.com/veis/p/7073076.html #include<stdio.h> ...
- 后端程序员之路 10、gbdt(Gradient Boosting Decision Tree)
1.GbdtModelGNode,含fea_idx.val.left.right.missing(指向left或right之一,本身不分配空间)load,从model文件加载模型,xgboost输出的 ...
- QQ 邀你上线小程序,官方生态能力持续赋能你的小程序
转: QQ 邀你上线小程序,官方生态能力持续赋能你的小程序 你身边总有一些朋友,他们的表情包极其丰富,能时刻应对各种聊天场景. 表情包奇奇怪怪,可可爱爱,非常形象生动体现我们当下的心情,逐渐成为社交平 ...
- 【资源下载】Linux下的Hi3861一站式鸿蒙开发烧录(附工具)
下载附件 2021春节前夕,华为发布了 HUAWEI DevEco Device Tool 2.0 Beta1,整体提供了异常强大的功能.得知消息后,我在第一时间带着无比兴奋的心情下载尝鲜,但结果却是 ...
- Golang+chromedp+goquery 简单爬取动态数据
目录 Golang+chromedp+goquery 简单爬取动态数据 Golang的安装 下载golang软件 解压golang 配置golang 重新导入配置 chromedp框架的使用 实际的代 ...
- java基础:变量、常量与作用域
变量就是可以变化的量,每个变量都必须声明其类型,Java 变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域.作用域 类变量 实例变量 局部变量常量初始化后不能在改变值,不会变动的值,它 ...
- Android R 新特性分析及适配指南
Android R(Android 11 API 30)于2020年9月9日正式发布,随国内各终端厂商在售Android设备的版本更新升级,应用软件对Android R 版本的兼容适配已迫在眉睫. 对 ...
- 一文读懂SuperEdge拓扑算法
前言 SuperEdge service group 利用 application-grid-wrapper 实现拓扑感知,完成了同一个 nodeunit 内服务的闭环访问 在深入分析 applica ...