-
简单介绍闭包
-
# 定义一个函数 def test(number): # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包 def test_in(number_in): print("in test_in 函数, number_in is %d"% number_in) return number+number_in #number_in其实是一个函数的引用,是把函数的引用当做参数来传递 # 其实这里返回的就是闭包的结果 return test_in #返回一定是内部函数的引用,不能带有小括号 # 给test函数赋值,这个20就是给参数 ret = test(20) # 在这里执行的是test函数,然后将test_in函数的引用返回,重新赋值给ret # 注意这里的100其实给参数 print(ret(100)) #在这里使用的ret(100) 相当于test_in(100) 也就相当于 test(20)(100) 最终返回的是 20+100 #注 意这里的200其实给参数 print(ret(200)) #在这里使用的ret(100) 相当于test_in(200) 也就相当于 test(20)(200) 最终返回的是 20+200
-
由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存
-
-
简单装饰器
-
首先我们需要一个闭包
-
def test(fun): def test_in(): #增加的功能 print("这是我新增的功能") return fun() #一般我们把函数的结果返回,不会自己直接执行 # 其实这里返回的就是闭包的结果 return test_in#返回一定是内部函数的引用,不能带有小括号
-
@test def fun(): return "rookieyu" print(fun())
-
装饰器 @test
-
相当于 fun = test(fun)
-
在这里调用的test ,然后把fun这个函数当做一个对象传递给test函数,返回的是test_in函数重新赋值给fun
-
最后我们在执行fun()的时候,相当于执行的是test(fun)() 是test_in函数。执行后会在函数里面先执行我们增加的功能,之后把函数之后的结果返回。
-
-
简单的装饰器,函数没有参数传递
-
-
简单装饰器的使用
-
函数带参数装饰器
-
def debug(func): def wrapper(something):# 指定宇宙无敌参数 print("[DEBUG]: enter {}()".format(func.__name__)) print('Prepare and say...',) return func(something) return wrapper # 返回 @debug def say(something): print("hello {}!".format(something)) say("rookieyu")
-
当我们的函数有参数的时候,需要在闭包内部的函数里面接收参数
-
-
通用装饰器
-
def debug(func): def wrapper(*args, *kwargs):# 指定宇宙无敌参数 print("[DEBUG]: enter {}()".format(func.__name__)) print('Prepare and say...',) return func(*args, *kwargs) return wrapper # 返回
-
我们采用的是*args, **kwargs,这样我们再调用装饰器的时候可以随意设置变量,让我们的装饰器更具有通用性
-
-
给装饰器传递参数一:
-
def logging(level): def wrapper(func): def inner_wrapper(*args, **kwargs): print("[{level}]: enter function {func}()".format(level=level,func=func.__name__)) return func(*args, **kwargs) return inner_wrapper return wrapper @logging(level='INFO') def say(something): print("say {}!".format(something)) # 如果没有使用@语法,等同于 # say = logging(level='INFO')(say) @logging(level='DEBUG') def do(something): print("do {}...".format(something)) if __name__ =='__main__': say('hello') do("my work")
-
采用三层函数嵌套的方式,最外层函数接收装饰器传递的参数
-
-
给装饰器传递参数二:
-
# 当前装饰器无法对被装饰的函数参数进行验证 def logging(level): def inner(fn): print(level) print("我的装饰器") return fn return inner @logging(level='INFO') def say(something): print("say {}!".format(something))
-
注意,当前装饰器外层接收的是装饰器的参数,内层装饰器参数是传递的被装饰函数的引用。
-
-
类装饰器
-
# 类装饰器 class Decorator(): def __init__(self,name): print(name) def __call__(self, *args, **kwargs): print("类装饰器") return args[0] @Decorator("rookieyu") def fun(a,b): print("这是函数") if __name__ == '__main__': fun(12,10)
-
使用模仿函数call方法,让类成为一个装饰器
-
-
给类里面函数加装饰器
-
# 给类的方法增加装饰器 def wapper2(fn): def inner(self): #self指的是装饰的类 print(self) print("给类增加装饰器") return fn(self) return inner class Demo(): @wapper2 def fun(self): print("这是当前类")
-
给类里面函数添加装饰器需要注意的是第一个参数是self,指的是当前类
-
-
给类增加装饰器
-
和普通函数差不多使用,不用传递第一个参数。也可以传递一个参数cls,代表是的这个类
-
def wapper(fn): def inner(cls): print("给类增加装饰器",cls) return fn return inner
-
def wapper3(): def inner(cls): print(cls) # 给雷增加属性 cls.name = "rookieyu" return cls return inner @wapper3() class Demo(): pass
-
-
如果想给类动态增加类属性,那么我们装饰器就需要接收参数了
-
def wapper3(name):
def inner(cls):
print(cls)
# 给雷增加属性
cls.name = "rookieyu"
return cls
return inner
@wapper3(name = 'rookie')
class Demo():
pass
if __name__ == '__main__':
print(Demo.name)
学IT,上博学谷