Python之函数(八)闭包与装饰器

闭包

  1. 闭包

    def func():
    	a=1
    	def f1():
    		def foo():
    			print(a)
    		return foo
    	return f1
    func()()()
    ret=func() #f1函数复制给ret
    a=ret() #foo函数复制给a
    a()#调用 foo函数
    #结果为1
    #在嵌套函数内,使用非全局变量(且不是本层变量)--就是闭包
    def func():
        a=[]
        def foo(price):
            a.append(price)
            avg=sum(a)/len(a)
            return avg #返回 平均值
        return foo
    ret=func()()
    print(ret(15000))
    #结果为:15000
    print(ret.__closure__)#判断是否是闭包
    # 了解:
    # print(ret.__code__.co_freevars)  # 获取的是自由变量
    # print(ret.__code__.co_varnames)  # 获取的是局部变量
    #闭包的作用:
    #保证数据的安全性
    #装饰器
    

4.15 装饰器

  1. 开放封闭原则

    • 此原则的基本思想是:
      • Open ( Open for extension ) 对扩展开放,模块的行为是灵活的。
      • Closed ( Closed for modification ) 对模块进行扩展的时候,不能影响已有的程序模块。
  2. 装饰器定义:在不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能。

  3. 无参数版

    • def wrapper(f):
          def inner():
              f()
          return inner
      
      @wrapper
      def func():
          print(1)
      func()
      
  4. 有参数版

    • import time
      def wrapper(f):
          def inner(*args,**kwargs):
              "被装饰前"
              start_time = time.time()
              f(*args,**kwargs) # func("alex")
              print(time.time() - start_time)
              "被装饰后"
          return inner  # 切记不要加括号
      
      @wrapper  # func = wrapper(func)
      def func(*args,**kwargs):
          print(f"这是{args}函数,李业还是不行")
          time.sleep(2) #模拟网络延时
      @wrapper  # foo = wrapper(foo)
      def foo(*args,**kwargs):
          print(f"这是{args}函数,常鑫穿齐*小短裤")
          time.sleep(3) #模拟网络延时
      func("alex","sur")
      foo("alex","sur")
      
  5. 带参装饰器

    • msg = """
      1.QQ
      2.wechat
      """
      avg = input('验证方式:')
      
      def auth(avg):
          def wrapper(f):
              def inner(*args,**kwargs):
                  if avg == 'QQ':
                      user = input('name')
                      pwd = input('password')
                      if user == 'alex' and pwd == '123456':
                          f()
                      else:
                          print('输入错误')
                  elif avg == 'wechat':
                      user = input('name')
                      pwd = input('password')
                      if user == 'lfz' and pwd == '123456':
                          f()
                      else:
                          print('输入错误')
              return inner
          return wrapper
      
      @auth(avg)   #func = auth(avg)(func)
      def func():
          print(1)
          
      func()
      
    • @auth('wechat') :分两步:

      • 第一步先执行auth('wechat')函数,得到返回值auth
      • 第二步@与auth2结合,形成装饰器@auth2 然后在依次执行。
  6. 多个装饰器装饰一个函数

    • def wrapper1(func):
          def inner1(*args,**kwargs):
              print("这是装饰器一开始")
              func(*args,**kwargs)
              print("这是装饰器一结束")
          return inner1
      
      def wrapper2(func):  
          def inner2(*args,**kwargs):
              print("这是装饰器二开始")
              func(*args,**kwargs)
              print("这是装饰器二结束")
          return inner2
      
      
      @wrapper1  
      @wrapper2  
      def func():
          print("这是被装饰的函数")
      
      func()
      # 结果:
      这是装饰器一开始
      这是装饰器二开始
      这是被装饰的函数
      这是装饰器二结束
      这是装饰器一结束
      
    • Python规定多个装饰器装饰一个函数的时候先执行离被装饰的函数最近的装饰器

原文地址:https://www.cnblogs.com/zhangdadayou/p/11415238.html