Python装饰器(闭包)

时间:2020-12-08 22:47:39

(一)函数作用域LEGB

LEGB:L>E>G>B

L: local函数内部作用域

E:enclosing函数内部与内嵌函数之间

G:global全局作用域

B:build-in 内置作用域(python解释器默认导入的一些变量,比如list,tuple等)

当查找一个变量时候,首先函数内部,然后是enclosing,接着是global,最后是build-in中。

passline=60
def func(val): #当定义一个函数的时候会引入本地作用域,函数调用的时候val就是本地变量
passline=90 #优先在本地变量查找
if val>=passline: #本地没有定义passline,因此向全局变量查找
print('pass')
else:
print('faild')
def in_func(): #(val,)应用变量后相当于添加属性中,属性和值是一个元组,是不变得。
print(val) #这里的val变量在函数in_func中未定义即本地变量没有,然后向上层encloding寻找,此时函数func内部有val
in_func()
def Max(val1,val2):
return max(val1,val2)#这里的max函数内部和全局都没有定义,当调用的时候逐层向上查找,最后在build-in中查找到
print(Max(80,100))
func(89)

(二)函数装饰器之闭包

闭包概念:
Closure:内部函数中对enclosing作用域的变量进行引用
函数实质与属性:
1,函数是一个对象(在内存中有存储的空间)
2,函数执行完后内部变量回收(如果中间产生一个变量,并且变量返回,则变量不会被回收)
3,函数属性
4,函数返回值
如果引用了外部enclosing变量,会将变量添加到函数属性中,当再次查找的时候,并不是去函数中查找,而是函数属性中查找
 
def set_passline(passline):    print('%x' % id(passline))    def cmp(val):        if val>=passline:            print('Pass')        else:            print('faild')    return cmpf_100=set_passline(60)f_150=set_passline(90)print(f_100)print(f_150)print(f_100.__closure__) #这里看出引用的变量作为函数的属性,调用函数的时候,直接使用print(f_150.__closure__)f_100(89)f_150(89)
结果:
5bc40930
5bc40cf0
<function set_passline.<locals>.cmp at 0x0000016956C5E950>
<function set_passline.<locals>.cmp at 0x0000016956C5E9D8>
(<cell at 0x0000016956C27C18: int object at 0x000000005BC40930>,)
(<cell at 0x0000016956C27C78: int object at 0x000000005BC40CF0>,)
Pass
faild
闭包作用:封装,代码复用
 
def my_sum(*arg):    print(arg)    return sum(arg)
def my_average(*arg):    return sum(arg)/len(arg)
def dec(func):    def in_dec(*arg):#闭包函数in_dec,函数func将放到in_dec的属性中,参数处理都是交给in_dec来处理,最后计算使用my_sum() print('in dec arg=',arg)        if len(arg)==0:            return 0        for val in arg:            if not isinstance(val,int):                return 0        return func(*arg) #这里的fuc是最初传进去的函数 return in_dec#调用dec函数,返回in_dec函数,in_dec函数调用my_sum函数#紧接着指示函数的赋值,函数的引用发生变化my_sum=in_dec(*arg)my_sum=dec(my_sum) #执行步骤是上面两步my_average=dec(my_average)print(my_sum(1,2,3,4,5))print(my_sum(1,2,3,4,5,'3'))print(my_average(1,2,3,4,5))print(my_average())

(三)python装饰器

1,装饰器用来装饰函数
2,返回一个函数对象
3,被装饰函数标识符指向返回的函数对象
4,语法糖 @deco
上面和闭包一样,装饰器就是对闭包的使用
 
def dec(func):    print('call dec')    def in_dec(*arg):        print('in dec arg=',arg)        if len(arg)==0:            return 0        for val in arg:            if not isinstance(val,int):                return 0        return func(*arg) #这里的fuc是最初传进去的函数 return in_dec@dec#my_sum=dec(my_sum)def my_sum(*arg):#my_sum=in_dec print(arg)    return sum(arg)print(my_sum(1,2,3,4,5))def my_average(*arg):    return sum(arg)/len(arg)
装饰器详解:
 
def deco(func):    def in_deco(x,y):        print('in deco')        func(x,y)    print('call deco')    return in_deco#当解释器执行到@deco时,会调用deco函数,并将bar作为参数传入,然后函数deco返回in_deco# bar=in_deco bar指向in_deco#当调用bar()时候,实际调用in_deco(),在in_deco调用过程中,我们重新调用了原来的bar()函数@decodef bar(x,y):    print('in bar',x+y)print(type(bar))bar(1,3)