Python的闭包和装饰器
一、闭包
1.1 闭包定义和作用
定义:闭包是为了保存局部变量的一种python语法。
官方解释:在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).
1.2 闭包使用
注意点(1) 闭包是没有办法改变上一级函数的值的
examp
def out1()
a=1
b=2
def iner()
a+=1
return inner
输出结果就会报错
形成闭包的两个条件 (1)必须有次级函数必须调用上一级的变量(2)必须返回自己的函数名
examp
def prime1():
a = 1
b = 2
def subpime(*args,**kwargs):
for i in args:
print(f'结果是{i*a}')
print(f'调用变量b相乘的结果{b+a}')
print(*args)
return subpime
f=prime1()
f(2,3,4)
prime1()(2,3,4) # 与上面两行的代码结果是一样的
输出结果
二、装饰器
2.1 装饰器 的定义和作用
定义:本质就是闭包
官方定义:装饰器本质上是一个Python函数(其实就是闭包),它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。装饰器用于有以下场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景
2.2 装饰器的使用
注意点(1) 要用函数做参数(2)要返回次级函数(3)参数之间要互相配对
2.2.1 函数装饰函数
**(1)**无参数情况
**(1) 用函数装饰函数
import time
def time_master(func):
def call_func(n):
print('开始计时...')
stime=time.time()
func(n)
etime=time.time()
print(f'一功能运行了{etime-stime:.2f}')
return call_func
@time_master#等同于myfun=time_master(myfunc)
#又因为返回了call_func函数,所以本质就是狸猫换太子
#把原来的myfun函数换成了call_func
def myfun(n):
time.sleep(2)
i=0
while(i<n):
i+=1
print('运算完成')
myfun(1000000)
**(2)**多参数情况
import time
def time_master(func):
def call_func(*args,**kwargs):
print('开始计时...')
stime=time.time()
func(*args,**kwargs)
etime=time.time()
print(f'一功能运行了{etime-stime:.8f}')
return call_func
@time_master
def myfun1(*args,**kwargs):
time.sleep(2)
sum,sum0 =0,0
for i in args:
sum+=i
for i in kwargs:
sum0+=kwargs.values()
print(f'元组的求和值为{sum},字典的求和值是{sum0}')
myfun1(1,2,3)
(3) 被装饰的函数带返回值情况
import time
def time_master(func):
def call_func(*args,**kwargs):
print('开始计时...')
stime=time.time()
t,n=func(*args,**kwargs)
etime=time.time()
print(f'一功能运行了{etime-stime:.8f}')
return t,n
return call_func
@time_master
def myfun1(*args,**kwargs):
time.sleep(2)
sum1,sum0 =0,0
for i in args:
sum1+=i
for i in kwargs:
sum0+=kwargs.values()
return sum1 ,sum0
t,n=myfun1(1,2,3)
print(f't的值是{t},n的值是{n}')
2.2.2 函数装饰类
def report(cls ):
def oncall(*args,**kwargs):
print('开始实例化对象')
_ =cls(*args,**kwargs)
print('对象完成实例化')
return _
return oncall
@report#相当于执行C=report(C),C就狸猫换太子换成了oncall函数
#因为为了把让实例化的类得到其返回值,就加上了return _
class C:
def __init__(self,x,y,z):
self.x=x
self.y=y
self.z=z
print('构造函数被调用')
c=C(1,2,3)
c.x
2.2.3 类装饰函数
class counter:
def __init__(self,func):
self.count=0
self.func=func
def __call__(self,n,m):
self.count+=1
print(f"以及被调用了{self.count}次")
return self.func(n,m)
@counter#等同于fun=counter(fun),fun就狸猫换太子,换成counter的实例化对象
def fun(n,m):
print('你好')
print(n,m)
fun(2,3)
fun(3,4)
fun(4,5)
2.2.4 类装饰类
这个我理解不了,暂时太难了,靠,用call魔法方法水一下,谢谢查看
python的__call__魔法方法
class A:
def __init__(self,exp):
self.exp=exp
def __call__(self,base,t):
return t*base**self.exp
#callable(A) 返回True
#这里A相当于是一个可以调用的对象了(python里面对象分为可以调用和不可以调用)
a=A(2)
a(3,1)#相当与计算1*3的平方,9
a(10,2)#相当于计算2*10的平方,200