zoukankan      html  css  js  c++  java
  • Python 入门之 Python三大器 之 装饰器

    1、开放封闭原则

    (1)代码扩展进行开放

    ​ 任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

    (2)修改源代码是封闭

    ​ 当我们写的一个函数,已经交付给其他人使用,如果这个时候对函数内部进行修改,或者修改了函数的调用方式,很有可能会影响其他已经在使用该函数的用户。

    在不修改源代码及调用方式的情况下,对功能进行额外的添加就是开放封闭原则。

    2、装饰器

    在不改变原被装饰的函数的源代码以及调用方式的情况下,为其添加额外的功能。

    (1)初识装饰器

    ​ 装饰(额外功能) 器(工具:函数)

    # 计算函数的运行时间
    import time
    
    def index():
        time.sleep(2)  
        print("这是小明写的功能")
    
    def func():
        time.sleep(1)  
        print("这是小刚写的功能")
    
    def red():
        time.sleep(2)  
        print("这是小红写的功能")
    
    start_time = time.time()  # 时间戳
    index()
    print(time.time() - start_time)
    
    start_time = time.time()  # 时间戳
    func()
    print(time.time() - start_time)
    
    start_time = time.time()  # 时间戳
    red()
    print(time.time() - start_time)
    
    # 注:(time.time() 此方法返回的是格林尼治时间,是此时此刻距离1970年1月1日0点0分0秒的时间秒数.也叫时间戳,它是一直变化的。)
    
    以上代码重复,繁琐
    改进:(将求时间写在一个函数中,函数就是以功能为导向,减少重复代码)
    如下:
    import time
    
    def index():
        time.sleep(2)  
        print("这是小明写的功能")
    
    def func():
        time.sleep(1)  
        print("这是小刚写的功能")
    
    def red():
        time.sleep(2)  
        print("这是小红写的功能")
    
    def times(func):
        start_time = time.time()  # 时间戳
        func()
        print(time.time() - start_time)
    
    times(index)
    times(func)
    
    改进:
    第一版装饰器
    import time
    
    def func():
        time.sleep(1)  
        print("这是小刚写的功能")
    
    def red():
        time.sleep(2)  
        print("这是小红写的功能")
    
    def index():
        time.sleep(2)  
        print("这是小明写的功能")
    
    def times(func):
        def foo():
            start_time = time.time()           # 时间戳  被装饰函数执行前干的事
            func()
            print(time.time() - start_time)    # 被装饰函数执行后干的事
        return foo                             # 不能加括号
    
    index = times(index)       # 不能加括号
    index()
    func = times(func)
    func()
    

    (2)语法糖 (Python 帮我们做的一个东西)

    要将语法糖写在被装饰函数的最上方
    def warpper(f):
        def inner():
            print("111")
            f()
            print("222")
        return inner
    
    # python帮咱们做的一个东西,语法糖
    @warpper                         # func = warpper(func)
    def func():
        print("被装饰的函数1")
    
    @warpper                         # index = warpper(index)
    def index():
        print("被装饰的函数2")
    
    func()
    
    def warpper(f):
        def inner(*args,**kwargs):
            print("被装饰函数执行前")
            ret = f(*args,**kwargs)
            print("被装饰函数执行后")
            return ret
        return inner
    
    @warpper
    def func(*args,**kwargs):
        print(f"被装饰的{args,kwargs}")
        return "我是func函数"
    
    @warpper
    def index(*args,**kwargs):
        print(11111)
    
    print(func(1,2,3,4,5,6,7,8,a=1))
    

    (3)标准版的装饰器

    def wrapper(func):
        def inner(*args,**kwargs):
            '''执行被装饰函数之前的操作'''
            ret = func()
            '''执行被装饰函数之后的操作'''
            return ret
        return inner
    
    # 这个就是标准的装饰器,完全符合代码开放封闭的原则。
    

    4、装饰器进阶

    (1)有参装饰器

    def auth(argv):
        def warpper(func):
            def inner(*args,**kwargs):
                if argv == "博客园":
                    print("欢迎登录博客园")
                    user = input("user:")
                    pwd = input("pwd:")
                    if user == 'yong' and pwd == "123":
                        func(*args,**kwargs)
                elif argv == "码云":
                    print("欢迎登录码云")
                    user = input("user:")
                    pwd = input("pwd:")
                    if user == 'liang' and pwd == "456":
                        func(*args, **kwargs)
            return inner
        return warpper
    
    def foo():
        print("被装饰的函数")
    
    msg = input("请输入您要登录的名字:")
    a = auth(msg)
    foo = a(foo)
    foo()
    
    def auth(argv):
        def wrapper(func):
            def inner(*args,**kwargs):
                if argv:
                    print("我加上功能了!")
                    func(*args,**kwargs)
                else:
                    func(*args,**kwargs)
            return inner
        return wrapper
    
    @auth(True)                            # @auth(true) -> argv=true,wrapper(foo) -> foo = inner -> inner()
    def foo():
        print("这是一个点燃")
    foo()
    

    (2)多个装饰器装饰一个函数

    多个装饰器装饰一个函数,先执行离被装饰函数最近的装饰器

    def auth(func):             # wrapper1装饰器里的 inner
        def inner(*args,**kwargs):
            print("额外增加了一道 锅包肉")
            func(*args,**kwargs)
            print("锅包肉 38元")
        return inner
    
    def wrapper1(func):        # warpper2装饰器里的 inner
        def inner(*args,**kwargs):
            print("额外增加了一道 刺生")
            func(*args,**kwargs)
            print("刺生 白吃")
        return inner
    
    def wrapper2(func):         # 被装饰的函数foo
        def inner(*args,**kwargs):
            print("额外增加了一道 麻辣哥")
            func(*args,**kwargs)
            print("难以下嘴")
        return inner
        
    def foo(): 
        print("这是一个虾饭店")
        
    foo = wrapper2(foo) # inner = wrapper2(foo)               #   #
    foo = wrapper1(foo) # inner = wrapper1(inner)           #       #
    foo = auth(foo)     # inner = auth(inner)             #           #
    foo()               # auth里边的inner()
    
    def auth(func):            # wrapper1装饰器里的 inner
        def inner(*args,**kwargs):
            print(123)
            func(*args,**kwargs)
            print(321)
        return inner
    
    
    def wrapper1(func):         # warpper2装饰器里的 inner
        def inner(*args,**kwargs):
            print(111)
            func(*args,**kwargs)
        return inner
    
    
    def wrapper2(func):          # 被装饰的函数foo
        def inner(*args,**kwargs):
            print(222)
            func(*args,**kwargs)
            print(567)
        return inner
    
    
    @auth                 # 1           7
    @wrapper1             #   2       6
    @wrapper2             #    3    5
    def foo():            #      4
        print("www.baidu.com")
    foo()
    
  • 相关阅读:
    CF 1083 A. The Fair Nut and the Best Path
    2434: [Noi2011]阿狸的打字机
    HDU 6086 Rikka with String
    HDU 2825 Wireless Password
    异常处理与补充模块
    面向对象
    初始socket
    面向对象的进阶(组合和继承)
    初始面向对象
    python之其他模块的用法
  • 原文地址:https://www.cnblogs.com/caiyongliang/p/11474816.html
Copyright © 2011-2022 走看看