zoukankan      html  css  js  c++  java
  • 闭包&装饰器

    闭包条件

    • 作用域 L_E_G_B
    • 函数中嵌套函数
    • 外层函数返回内存嵌套函数名
    • 嵌套函数有引用一个非全局据变量(E作用域)
    def func():
        a = 100  # Enclosed作用于
    
        def inner():
            print(a)
    
        return inner
    
    
    f = func()
    print(f)  # 返回inner函数对象
    f()  # 执行inner函数
    

    作用:实现数据锁定,提高稳定性

    装饰器

    • 知识储备:

      • 作用域 L_E_G_B
      • 高阶函数 :1.函数名可以作为参数传入;2.函数名还可以作为返回值
      • 闭包
    • 解释:

      • 装饰函数是一个闭包样式的函数,参数是被装饰函数
      • 被装饰函数会当作参数传入装饰函数中,然后返回给被装饰函数接收,所以我们执行被装饰函数的时候就等于执行装饰器函数的返回值--嵌套函数
    • 目的:遵循原则,开放扩展 关闭修改

    • 好处

      • 在不改变原函数功能的情况扩展功能
      • 执行原函数就能执行到扩展功能
    • 装饰器的应用场景

      • 登陆验证
      • 函数运行时间统计
      • 执行函数之前做准备工作
      • 执行函数后做清理功能
    # 添加时间统计的装饰器
    def add_time(func):
        # *args, **kwargs作用:有参数无参数的函数都能装饰 
        def inner(*args, **kwargs):
            before_time = time.time()
            func(*args, **kwargs)
            after_time = time.time()
            print(after_time - before_time)
    
        return inner
    
    
    @add_time
    def for_fun():  # for_fun=add_time(for_fun)   add_time(for_fun) == inner 
        for i in range(100):
            if i == 50:
                time.sleep(1)
                print(i)
    
    
    # 所以执行for_fun的时候等于执行的inner
    for_fun()
    
    # 登陆验证的装饰器,每个页面验证登陆 如果登陆过不需要重复登陆
    # txt数据
    # {"name":"a","passwd":"1"}
    # {"name":"b","passwd":"2"}
    # {"name":"c","passwd":"3"}
    
    cookie = "False"
    def check_login(func):
        def inner(*args, **kwargs):
            global cookie
            if cookie == "False":
                print("身份验证失败请重新登陆")
                n = 0
                while n < 4:
                    username = input("请输入你的用户名").strip()
                    passwd = input("请输入你的密码").strip()
                    # 读取用户信息文件,判断帐号密码
                    with open("login_info.txt", "r", encoding="utf-8") as file:
                        for line_info in file:
                            user_info = eval(line_info.strip())
                            if username == user_info["name"] and passwd == user_info["passwd"]:
                                print("登陆成功")
                                cookie = "True"
                                func(*args, **kwargs)
                            
                        else:
                            print("用户名不存在或密码错误")
                            n += 1
                else:
                    print("错误次数过多,退出登陆")
            else:
                func(*args, **kwargs)
               
        return inner
    
    
    @check_login
    def home():
        print("欢迎来到首页")
    
    
    @check_login
    def me():
        print("欢迎来到个人中心")
    
    
    print(home())
    print(me())
    
    
    • 装饰器装饰类
      • 将类对象传进装饰器,逻辑和装饰函数一样
      • 嵌套函数需要返回类实例对象
    # 类装饰器,reture 实例对象即可
    def Myfunc(cls):
        def inner(*args, **kwargs):
            print("进入装饰器")
            # cls是传进来的类 被执行实例化对象,初始化实例对象初始值
            # # 必须将对象返回给调用方接收实例
            return cls(*args, **kwargs)
    
        return inner
    
    
    @Myfunc
    class MyClass:  # MyClass=Myfunc(MyClass)
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    
    # 实例化对象是执行装饰器内层函数后 返回的一个实例对象给m接收
    m = MyClass("DaBai", 18)
    print(m)  # <__main__.MyClass object at 0x000001E76D6A0358> 实例对象 
    print(m.name)
    
    

    类中常用的三个装饰器

    • @classmethod 标记为类方法,默认参数为"cls",类本身可以直接调用(类属性,类方法,类本身和实例都可以直接调用,实例属性和实例方法,类本身不能调用,所以将方法加上@classmethod 装饰器变成类方法后类本身就可以直接调用了)
    • @staticmethod 标记为静态方法,默认不需要传参,类和实例都能调用
    • @property 设置只读属性,被property装饰的方法可以像属性一样被实例调用,但是属性值为只读属性,不能被修改(毕竟原始还是个方法)
    # 三个类装饰器
    class MyTest(object):
    
        def __init__(self, name):
            self.name = name
    
        @classmethod  # 类方法
        def add(cls):  # 默认参数传cls==类本身,self==实例本身
            print("add方法")
            # print(cls)
    
        @staticmethod  # 静态方法 类本身和实例对象都能调用
        def static():  # 默认不需要传参数,不像类方法默认传cls,实例方法默认传self
            print("这个是静态方法")
    
        @property  # 作用:设置实例的只读属性,不允许被修改 ,不允许修改的属性这样设置
        def Name(self):
            print("被这个装饰的类方法,可以像是属性一样被调用")
            name = "pro"
            return name
    
        def run(self):
            print(self.name)  # 实例属性 name 可以修改
            print(self.Name)  # 被@property装饰的方法可以像属性一样调用,不可被修改
    
    
    # 实例
    t = MyTest("DaBai")
    
    # 类方法(classmethod)
    MyTest.add()  # 类直接调用
    t.add()  # 实例也能调用
    
    # 静态方法(staticmethod)
    MyTest.static()  # 类直接调用
    t.static()  # 实例也能调用
    
    # 只读方法(property)实例方法可以像属性一样调用
    # 实例属性允许被修改或者添加
    print(t.name)
    t.name = "Bai"
    print(t.name)
    
    # property  设置只读属性不允许被修修
    # t.Name = "PRO"  # 报错:AttributeError: can't set attribute
    print(t.Name)  # 被property装饰的方法可以像属性一样调用 但是属性值为只读属性,不能被修改(毕竟原始还是个方法)
    
    t.run()
    
    
  • 相关阅读:
    【翻译/介绍】jump consistent hash:零内存消耗,均匀,快速,简洁,来自Google的一致性哈希算法 [2015-03-13]
    现代密码学实践指南[2015年]
    本博客迁走了
    高性能web系统的架构和系统优化
    vs 2013调试的时候重启的解决方案
    年会与项目管理
    javascript 关闭窗口,弹出新窗口并带有确认关闭对话框解决办法
    成长
    POCO exception
    通过OpenGL ES在iOS平台实践增强现实(二)
  • 原文地址:https://www.cnblogs.com/jiangmingbai/p/10903617.html
Copyright © 2011-2022 走看看