Python装饰器(闭包)

(一)函数作用域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  cmp

f_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
.cmp at 0x0000016956C5E950>
.cmp at 0x0000016956C5E9D8>
(,)
(,)
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()函数
@deco
def bar(x,y):
    print('in bar',x+y)
print(type(bar))
bar(1,3)


你可能感兴趣的:(python)