zoukankan      html  css  js  c++  java
  • 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规定多个装饰器装饰一个函数的时候先执行离被装饰的函数最近的装饰器

  • 相关阅读:
    函数和常用模块【day06】:shutil模块(四)
    函数和常用模块【day06】:time模块 (一)
    函数和常用模块【day05】:生成器并行计算(五)
    函数和常用模块【day05】:装饰器前奏(一)
    函数和常用模块【day04】:内置函数(八)
    函数和常用模块【day04】:作用域、局部和全局变量(四)
    函数和常用模块【day04】:函数的非固定参数(三)
    Python基础【day02】:元组和购物车练习的知识点
    Python基础【day02】:字符串(四)
    Python基础【day03】:入门知识拾遗(八)
  • 原文地址:https://www.cnblogs.com/zhangdadayou/p/11415238.html
Copyright © 2011-2022 走看看