• 装饰器


    decorator

    装饰器 可以给函数动态加上功能,对于类的方法,装饰器一样起作用。

    既要保护类的封装特性,又要让开发者可以使用“对象.属性”的方式操作操作类属性,除了使用 property() 函数,Python 还提供了 @property 装饰器。通过 @property 装饰器,可以直接通过方法名来访问方法,不需要在方法名后添加一对“()”小括号。

    @property 的语法格式如下:

    @property
    def 方法名(self)
        代码块
    

     

    对实例属性操作的时候,该属性是不直接暴露的,而是通过getter和setter方法来实现的。还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:

    class Rect:
        def __init__(self,area):
            self.__area = area
    
        @property
        def area(self):
            return self.__area
    
        @area.setter
        def area(self, value):
            self.__area = value
    
        @area.deleter
        def area(self):
            self.__area = 0
        
    
    
    rect = Rect(30)
    #直接通过方法名来访问 area 方法
    print("矩形的面积是:",rect.area)
    
    # 为 Rect 类中的 area 方法添加 setter 方法 后
    rect.area = 90
    print("修改后的面积:",rect.area)
    
    del rect.area
    print("删除后的area值为:",rect.area)

    自定义装饰器

    参考文章:https://zhuanlan.zhihu.com/p/85917478

    def wrapper(func):
        def inner(*args,**kwargs):
            '''被装饰函数之前'''
            ret = func(*args,**kwargs)
            '''被装饰函数之后'''
            return ret
        return inner

    编写一个装饰器函数`log_time`,被装饰的函数执行时打印出【函数名】与【执行时间】(时间单位为秒,只需保留小数点后一位,见测试示例)。
    注:装饰器函数要具备通用性,即被装饰函数允许传入位置参数与关键字参数。

    import time
    import functools
    def log_time(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
         '''执行前相关操作'''  t_begin
    = time.time() ret = func(*args, **kwargs)
         '''执行后相关操作'''
    print('%s: Function [saySomething] took %0.1f seconds to execute' % (func.__name__, time.time()-t_begin)) return ret return inner # 这里是测试代码 @log_time def salute(word): time.sleep(2) print(word) salute('hello') # 'hello Function [saySomething] took 2.0 seconds to execute'

    函数装饰之后,相当于执行了inner函数,所以输出inner,wraps将 被修饰的函数(wrapped) 的一些属性值赋值给修饰器函数(wrapper) ,最终让属性的显示更符合我们的直觉

    装饰器传参

    import time
    def timmer(f):
        def inner(a,b):
            start_time = time.time()
            f(a,b)
            end_time = time.time()
            print('此函数的执行时间为{}'.format(end_time - start_time))
        return inner
    
    @timmer
    def func1(a,b): print('in func1 {}{}'.format(a,b)) time.sleep(1) # 模拟程序逻辑 func1(1,2) 执行输出: in func1 12 此函数的执行时间为1.0006024837493896

    如果有多个参数呢?改成动态参数

    import time
    def timmer(f):
        def inner(*args,**kwargs):
            start_time = time.time()
            f(*args,**kwargs)
            end_time = time.time()
            print('此函数的执行时间为{}'.format(end_time - start_time))
        return inner
    @timmer
    def func1(*args,**kwargs):
        print('in func1 {}{}'.format(args,kwargs))
        time.sleep(1)  # 模拟程序逻辑
    func1(1,2,a='3',b=4) 
    执行输出:
    in func1 (1, 2){'b': 4, 'a': '3'}
    此函数的执行时间为1.000101089477539

    函数的执行时,*打散 ; 函数的定义时,*聚合。

    import time                                 #1.加载模块
    def timmer(*args,**kwargs):                     #2.加载变量  5.接收参数True,2,3
        def wrapper(f):                             #6.加载变量  8.f = func1
            print(args, kwargs)                     #9.接收timmer函数的值True,2,3
            def inner(*args,**kwargs):                 #10.加载变量. 13.执行函数inner
                if flag:                         #14 flag = True
                    start_time = time.time()             #15 获取当前时间
                    ret = f(*args,**kwargs)             #16 执行func1
                    time.sleep(0.3)                 #19 等待0.3秒
                    end_time = time.time()             #20 获取当前时间
                    print('此函数的执行效率%f' % (end_time-start_time)) #21 打印差值
                else:
                    ret = f(*args, **kwargs)
                return ret                         #22 返回给函数调用者func1()
            return inner                         #11 返回给函数调用者wrapper
        return wrapper                         #7.返回给函数调用timmer(flag,2,3)
    flag = True                                 #3 加载变量
    @timmer(flag,2,3)      # 4.执行函数timmer(flag,2,3) 17.执行函数func1 两步:1,timmer(flag,2,3) 相当于执行wrapper                                                     2.@wrapper 装饰器 func1 = wrapper(func1)
    def func1(*args,**kwargs):
        return 666                             #18 返回给函数调用者f(*args,**kwargs)
    print(func1())                             #12 执行函数 

    装饰器的 __name__ 和 __doc___

    __name__:函数名

    __doc___:函数的解释

  • 相关阅读:
    在基础数据类型和在对象中 使用 == 与equals的差别
    对Java中静态代理和动态代理的简单理解
    MyBatis中sqlSession的创建及执行流程
    Spring相关概念
    AOP相关
    IOC容器和Bean的配置
    如何将本地项目上传到GitHub进行托管
    稀疏数组
    Java集合回忆
    JSTL标签库
  • 原文地址:https://www.cnblogs.com/Mint-diary/p/14450732.html
Copyright © 2020-2023  润新知