装饰器

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___:函数的解释

原文地址:https://www.cnblogs.com/Mint-diary/p/14450732.html