找回密码
 立即注册
首页 资源区 代码 2019-07-11 闭包函数和装饰器

2019-07-11 闭包函数和装饰器

慷规扣 4 天前
一、闭包函数
  定义:定义在内部的函数引用外部函数的名字(变量)叫做闭包函数
  要打印的是inner函数的x,因为这个函数里面没有定义x的值,所以找上一层的局部变量x = 111。执行代码,outter函数被调用,返回值为inner,用变量res接收,所以res = inner,下面再用res(),就是inner(),调用inner函数,执行里面代码,打印结果为111
  1. def outter():
  2.     x = 111
  3.     def inner():
  4.         print(x)
  5.     return inner
  6. res = outter()  # res就是inner函数内存地址
  7. res()    #111
复制代码
  给函数体传值的两种方式:
    1.函数调用时候直接传参
  1. def index1(username):
  2.     print(username)
  3. res = index1('aa')      #aa
复制代码
    2.闭包传参
  这个和刚开始定义的闭包函数一样只不过是把变量x,y放在outter函数里面当形参,在调用的时候传实参
  1. def outter(x,y):
  2.     # x = 1
  3.     # y = 40
  4.     def my_max():
  5.         if x > y:
  6.             return x
  7.         return y
  8.     return my_max
  9. res1 = outter(1,40)  # res就是my_max函数的内存地址
  10. print(res1())    #40
复制代码
 
二、装饰器
  定义:给被装饰的对象添加新的功能的一个工具。  目的:更方便的使用新添加的新功能
  装饰器(可调用对象)必须遵守的两个原则:
    1.不可改变被装饰对象的代码
    2.不可改变 被装饰对象的调用方式(假如调用方式是idnex(),使用装饰器之后也是这种调用方式)
  
  简单版本:
  在原始函数index函数上加一个时间计算功能,最后也是调用了index(),没有违反装饰器的两个原则。运行函数先到outter调用,里面传一个参数index(这个是最原始的index函数的内存地址),然后返回get_time,用变量index接收。index()其实就是调用get_time函数。执行里面代码,func()就是之前传的func参数,index()调用。
  1. import time
  2. def index():
  3.     time.sleep(3)
  4.     print('睡醒了')
  5. def outter(func):  # func = 最原始的index函数的内存地址
  6.     def get_time():
  7.         start = time.time()
  8.         func()  # func = index函数的内存地址() 直接调用
  9.         end = time.time()
  10.         print('index run time:%s'%(end-start))
  11.     return get_time
  12. index = outter(index)  # outter(最原始的index函数内存地址)
  13. # index指向get_time函数的内存地址
  14. index()   #睡醒了
复制代码
1.png

  升级版本:(被装饰的函数需要参数,之前的用法需要在get_time里面的func()写参数,才能使用正确。统一参数写法:*args,**kwargs)
2.gif
3.gif
  1. import time
  2. def index():
  3.     time.sleep(3)
  4.     print('澳门最大线上赌场开业啦 性感tank在线发牌!')
  5.     return 'index'
  6. # res1 = index()
  7. def login(name):
  8.     time.sleep(1)
  9.     print('%s is sb'%name)
  10.     return 'login'
  11. # res = login('egon')
  12. def outter(func):  # func = 最原始的login函数的内存地址
  13.     def get_time(*args, **kwargs):  # args = ('egon',) kwargs = {}
  14.         start = time.time()
  15.         res = func(*args, **kwargs)  # 最原始的login函数的内存地址() 直接调用  func('egon')
  16.         end = time.time()
  17.         print('func run time:%s'%(end-start))
  18.         return res
  19.     return get_time
  20. login = outter(login)  # outter(最原始的login函数的内存地址)
  21. res = login('egon')
  22. print(res)
  23. index = outter(index)
  24. res1 = index()
  25. print(res1)
复制代码
代码  这样设置之后可以接受任意参数的函数。
 三、装饰器语法糖
  语法糖在书写的时候应该与被装饰器紧紧挨着,两者之间不要有空。把装饰器赋值给紧挨这的的可调用对象,并且把紧挨着的函数名当做参数传递到装饰器中
4.png

 
  1. def outter(func):
  2.     def inner(*args,**kwargs):
  3.         #调用被装饰对象 (为被装饰对象添加新功能)
  4.         func(*args,**kwargs)
  5.         print('inner')
  6.     return inner
  7. @outter   #index = outter(index)  -->  index = inner
  8. def index():
  9.     print('index')<br>
  10. index()  # -->inner()
复制代码
  
四、多个装饰器一起使用
   注意:装饰器装饰顺序:从下往上
        装饰器执行效率:从上往下
 
 
5.png

 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册