zoukankan      html  css  js  c++  java
  • 第十四天

    装饰器

    """
    装饰器
    """
    # AOP :面向切面,可以看成OOP的升级
    # 在python中 装饰器相当于AOP的编程思想
    # 闭包:在内部函数中访问外部函数的变量。外部函数中直接返回内部函数的名字
    # (1)嵌套函数 (2)内部函数访问外部变量 (3) 外部函数return inner名字
    # 闭包的例子
    def outer():
    x=1
    def inner():
    x=2
    print(x)
    return inner
    inner_new=outer()
    inner_new()
    print(inner_new.__closure__)

    一、 装饰器的基本原理
    1. 背景例子
    # 实现bill上下班打卡
    def on_duty(name):
    print("{}上班".format(name))
    def off_duty(name):
    print("{}下班了".format(name))
    on_duty("bill")
    off_duty("bill")

    # 需求变更,要求在上下班打卡后,显示时间
    from datetime import datetime
    def on_duty(name):
    print("{}上班了".format(name))
    # check_in()
    def off_duty(name):
    print("{}下班了".format(name))
    # check_in()
    on_duty("bill")
    off_duty("bill")

    def check_in():
    print(datetime.now())
    def new_onduty(name):
    on_duty(name)
    check_in()
    new_onduty("bill")

    # 闭包
    # 1. 希望调用的时候,方法名字还叫onduty 闭包返回的就是 函数的名字
    # 2. 希望checkin 函数加到onduty的功能中 闭包中如果参数直接使用函数的名字
    def on_duty(name):
    print("{}上班了".format(name))
    def off_duty(name):
    print("{}下班了".format(name))

    # 在闭包传入的参数中,名字应该是函数的名字,闭包外部函数可以装饰任何一个名字
    def chekc_in(on_duty):
    def inner(name):
    on_duty(name)
    print(datetime.now())
    return inner
    on_duty=check_in(on_duty)
    on_duty("bill")
    off_duty=check_in(on_duty)
    off_duty("bill")

    # 装饰器的定义:就是一个函数,专门在不改变原有函数的基础上,对原有函数进行扩充。(闭包思想)
    """
    def decortor(原函数名):
    return 新函数名
    """

    # 装饰器解决
    # 装饰器定义好之后,怎么使用?
    """
    在需要装饰的函数上面[@装饰器函数的名字]相当于代替on_duty=check_in(on_duty)
    想当于执行了
    fun=decoartor(fun)

    # 语法糖:能够使用特殊的语法来方便程序员调用的方式,都叫语法糖
    """
    def check_in(fun):
    def inner(name):
    result=fun(name)
    print(datetime.now())
    return result
    return inner
    @check_in
    def on_duty(name):
    print("{}上班了".format(name))
    @check_in
    def off_duty(name):
    print("{}下班了".format(name))

    on_duty=chekc_in(on_duty)
    on_duty("bill")
    off_duty=chekc_in(off_duty)
    off_duty("bill")

    二、 装饰器的优化
    # 对于参数的优化:使用万能参数作为装饰器内部函数的参数。
    # 这样装饰器就可以应用到其他的功能函数上
    def check_in(fun):
        def inner(*args,**kwargs):
            fun(*args,**kwargs)
            print(datetime.now())
        return inner
    @chekc_in
    def on_duty(name):
        print("{}上班了".format(name))
    @chekc_in
    def off_duty(name):
        print("{}下班了".format(name))
    
    on_duty=chekc_in(on_duty)
    on_duty("bill")
    off_duty=chekc_in(off_duty)
    off_duty("bill")
    

      

    # 对于返回值也可以获得
    def check_in(fun):
    def inner(*args,**kwargs):
    result=fun(*args,**kwargs)
    print(datetime.now())
    return result
    return inner
    @chekc_in
    def on_duty(name):
    print("{}上班了".format(name))
    return "success"
    result=on_duty("bill")
    print(result)

    三、 装饰器的叠加
    """
    decorator1装饰fun,decorator2装饰decorator1修饰好的fun
    @decorator2
    @decorator1
    def fun():
    pass
    """
    def record(fun):
    def inner(*args,**kwargs):
    result=fun(*args,**kwargs)
    print( result+"dddd""向领导汇报工作")
    return inner
    # def check_in(fun):
    # def inner(*args,**kwargs):
    # result=fun(*args,**kwargs)
    # print(datetime.now())
    # return result
    # return inner
    @record
    @check_in
    def on_duty(name):
    print("{}上班了".format(name))
    return "success"
    result=on_duty("bill")
    print(result)

    on_duty=check_in(on_duty)
    on_duty=record(on_duty)
    on_duty()

    # 注意:装饰器,参数一定是固定,只能是被装饰的函数名,不能再加任何一个参数
    def check_in(format):
    def inner_check_in(fun):
    def inner(*args,**kwargs):
    fun(*args,**kwargs)
    print(datetime.strftime(datetime.now(),format))
    return inner
    return inner_check_in
    def record(fun):
    def inner(*args,**kwargs):
    fun(*args,**kwargs)
    print("汇报工作")
    return inner
    @record
    # 在装饰器调用时,可以传入参数,使用的时候,@语法糖(参数的值)
    @check_in("%Y-%m-%d %H:%M:%S")
    def on_duty(name):
    print("{}上班了".format(name))
    @record
    @check_in("%Y-%m-%d %H:%M:%S")
    def off_duty(name):
    print("{}下班了".format(name))


    on_duty("bill")
    off_duty("bill")

    四、 保留函数的元信息

    # 因为我们的函数使用装饰器之后,名字、说明文档、注释,都被inner相关信息给覆盖了
    # 可以使用functools.wraps
    from functools import wraps
    def check_in(fun):
    @wraps(fun)
    def inner(*args,**kwargs):
    fun(*args,**kwargs)
    print(datetime.now())
    return inner
    @check_in
    def on_duty(name :str) -> None:
    """
    这是一个上班的函数
    """
    print("{}上班了".format(name))
    @check_in
    def off_duty(name):
    print("{}下班了".format(name))

    on_duty("bill")
    # __name__可以返回函数的名字
    print(on_duty.__name__)
    print(on_duty.__doc__)
    print(on_duty.__annotations__)

    装饰器类 (类装饰器)
    class CheckIn:
    def __init__(self,fun):
    self.fun=fun
    def __call__(self, *args, **kwargs):
    self.fun(*args, **kwargs)
    print(datetime.now())
    @CheckIn
    def on_duty(name :str) -> None:
    """
    这是一个上班的函数
    """
    print("{}上班了".format(name))
    # on_duty=CheckIn(on_duty)
    on_duty("bill")

    # 练习:实现一个对程序记录日志的功能

    # 日志的信息:方法的名字、传入的参数,运行时间,得到返回值,当前的操作时间
    # 思路: 日志装饰器函数,闭包,显示元信息
    import time
    def log(funname):
    def inner(*args, **kwargs):
    print("这是程序日志start")
    # 传入的参数 *args,**kwargs
    argsStr = []
    if args:
    argsStr.append("".join([str(i) for i in args]))
    if kwargs:
    argsStr.append("".join(["%s=%s" % (k, v) for k, v in kwargs.items()]))

    opertime = datetime.now()
    start = time.time()
    result = funname(*args, **kwargs)
    time.sleep(1)
    end = time.time()
    text = """
    这是日志信息:
    当前方法的名字是{}
    当前方法传入的参数是{}
    当前方法操作的时间是{};
    当前方法执行的时间是{};
    当前方法的返回值是{}

    """
    fn = funname.__name__
    print(text.format(fn, argsStr, opertime, end - start, result))
    return result
  • 相关阅读:
    npm脚本和package.json
    Vue官方文档笔记(二)
    Vue官方文档笔记
    2019windows上安装Mac OS 10.14过程详细截图
    三次握手四次挥手
    ==和equals的区别
    Stringbuffer和Stringbuilder的区别
    字符串拼接五种常用方法
    什么是线程以及保证线程安全
    什么是线程安全,怎样保证线程安全
  • 原文地址:https://www.cnblogs.com/ztx695911088/p/9115020.html
Copyright © 2011-2022 走看看