Python装饰器的具体实用示例

您所在的位置:网站首页 pythontime函数重新计时 Python装饰器的具体实用示例

Python装饰器的具体实用示例

2023-03-14 22:14| 来源: 网络整理| 查看: 265

示例1:普通装饰器 def name(n):     def func(x):         res = n(x+x)         return res     return func @name def run(x):     # run = name(run)     print(x) if __name__ == '__main__':     run(1) # 2 def name(n):     def func(*x):         res = n(x+x)         return res     return func @name def run(x):     # run = name(run)     print(x) if __name__ == '__main__':     run(1) # (1, 1)

上述二者的比较,注意传参参数。一个是普通的传值,一个是两个元组相加。

示例2:普通装饰器传值 def name(n):     def func(x, y):         res = n(x,y)         return res     return func @name def run(x, y):  # run = name(run)     print(x, y) if __name__ == '__main__':     run(1, 2) # 1 2

试想,如何才能实现1+2,run函数中还是name函数中

def name(n):     def func(x, y):         res = n(x,y)         return res     return func @name def run(x, y):  # run = name(run)     print(x + y) if __name__ == '__main__':     run(1, 2)

在run函数中实现,name函数作用近似于调用的操作,也可以在name函数中实现

def name(n):     def func(x, y):         res = n(x,y)         print(x + y)         return res     return func @name def run(x, y):  # run = name(run)     # print(x + y)     pass if __name__ == '__main__':     run(1, 2) 示例3-进阶:日志 import logging def name(n):     def func(x, y):         res = n(x,y)         logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '                                    '%(lineno)d    %(message)s', level=logging.DEBUG)         logging.info("执行了{},{},结果是{}".format(x,y,res))         return res     return func @name def run(x, y):  # run = name(run)     return x+y if __name__ == '__main__':     run(1, 2) # 2023-03-01 12:24:10,474  root  20 ceshi_test.py 10    执行了1,2,结果是3

这里的结果貌似没有指明函数,影响不大,可以看看logging模块,也可以自己加。

import logging def name(n):     def func(x, y):         res = n(x,y)         logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '                                    '%(lineno)d  %(funcName)s %(message)s', level=logging.DEBUG)         logging.info("执行了{},{},{},结果是{}".format(n.__name__,x,y,res))         return res     return func @name def run(x, y):  # run = name(run)     return x+y if __name__ == '__main__':     run(1, 2) # 2023-03-01 12:35:15,283  root  20 ceshi_test.py 9  func 执行了run,1,2,结果是3

可以看到,获取的运行函数其实不太一样。要想准确的获取,建议手写

示例4-进阶:时间计时器 import time def timer(clock):     def func(*args,**kwargs):         start = time.time()         res = clock(*args,**kwargs)         print("耗时 {} S".format(time.time() - start))         return res     return func @timer def run(x, y):      time.sleep(1)     print(x + y) if __name__ == '__main__':     run(1, 2) # 3 # 耗时 1.0103626251220703 S

上述是在不做任何操作的情况下,单纯用来计算程序运行时间。

示例5-再进阶-带参 def outwapper(out):     def country(cont):         def inwapper(*args,**kwargs):             if out == '中国':                 print("你好啊,兄弟")             else:                 print("你是哪个国家的")             cont(*args,**kwargs)         return inwapper     return country @outwapper("中国") def people():     pass if __name__ == '__main__':     people()

是不是看起来麻烦了很多,仔细一看其实也久那么回事。传个参数,该返回的值还是得返回。

def outwapper(out):     def country(cont):         def inwapper(*args,**kwargs):             if out == '中国':                 print("你好啊,兄弟")             else:                 print("你是哪个国家的")             cont(*args,**kwargs)         return inwapper     return country @outwapper("中国") @outwapper("俄罗斯") def people():     pass if __name__ == '__main__':     people() # 你好啊,兄弟 # 你是哪个国家的

可以多个装饰器作用同一个函数上,也能重复使用。

示例6-高阶-类装饰器 class Time(object):     def __init__(self, func):         self.func = func     def __call__(self, *args, **kwargs):         print(args,kwargs) @Time def name():     pass if __name__ == '__main__':     name()

套用格式即可,__init__中的参数是必须的,因为需要传递函数。

class Time(object):     def __init__(self, func):         self.func = func     def __call__(self, *args, **kwargs):         print(args,kwargs) @Time def name(x,y):     pass if __name__ == '__main__':     name('清安',age=18) # ('清安',) {'age': 18}

很明显了吧,__call__中用来接收值并处理的。

传参 class Time(object):     def __init__(self, func):         self.func = func     def __call__(self, evt):         def wapper(*args, **kwargs):             print(self.func, args, kwargs)         return wapper @Time("中国") def name(x, y):     pass if __name__ == '__main__':     name('清安', age=18) # 中国 ('清安',) {'age': 18}

evt是啥?

class Time(object):     def __init__(self, func):         self.func = func     def __call__(self, evt):         def wapper(*args, **kwargs):             print(evt.__name__, args, kwargs)         return wapper @Time("中国") def name(x, y):     print(x,y) if __name__ == '__main__':     name('清安', age=18) # name ('清安',) {'age': 18}

就是name函数的函数地址,如何使用evt参数呢?

class Time(object):     def __init__(self, func):         self.func = func     def __call__(self, evt):         def wapper(*args, **kwargs):             evt(args,kwargs)             # print(evt.__name__, args, kwargs)         return wapper @Time("中国") def name(x, y):     print(x,y) if __name__ == '__main__':     name('清安', age=18)

就是这么简单。

示例7-高阶-装饰类的装饰器 def func(cls):     def inwapper(*args,**kwargs):         print(cls.__name__)         print(args)     return inwapper @func class User:     def __init__(self,name):         self.name = name if __name__ == '__main__':     User("清an") # User # ('清an',) 类中函数使用装饰器 def func(cls):     def inwapper(x, *args, **kwargs):         logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '                                    '%(lineno)d  %(funcName)s %(message)s', level=logging.DEBUG)         logging.info("执行了{},结果是{},{},{}".format(cls.__name__,x, args, kwargs))     return inwapper # @func class User:     @func     def name(self, name, name1, age):         # return name, name1, age         pass if __name__ == '__main__':     u = User()     u.name("清安","ANAN",age=18) 2023-03-01 18:36:36,310  root  20 ceshi_test.py 74  inwapper 执行了name,结果是,('清安', 'ANAN'),{'age': 18}

为什么要有个x,因为self会被当作参数传递,直接把内存地址一起传走了,要么下标取值要么再来个参数接收这个self。要么类中不使用self

既然使用了self,那么装饰器中能用来调用属性吗,答案是当然可以。

❞ def func(cls):     def inwapper(x, *args, **kwargs):         logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '                                    '%(lineno)d  %(funcName)s %(message)s', level=logging.DEBUG)         x.info = 1         logging.info("执行了{},结果是{},{},{}".format(cls.__name__,x, args, kwargs))     return inwapper class User:     info = None          @func     def name(self, name, name1, age):         # return name, name1, age         pass if __name__ == '__main__':     u = User()     u.name("清安","ANAN",age=18)     print(u.info) # 1 # 2023-03-02 09:15:36,640  root  20 ceshi_test.py 75  inwapper 执行了name,结果是,('清安', 'ANAN'),{'age': 18} ❝

显而易见,赋值成功。再来看看对其他函数赋值。

❞ def func(cls):     def inwapper(x, *args, **kwargs):         logging.basicConfig(format='%(asctime)s  %(name)s  %(levelno)s %(filename)s '                                    '%(lineno)d  %(funcName)s %(message)s', level=logging.DEBUG)         x.Info("QA",18)         logging.info("执行了{},结果是{},{},{}".format(cls.__name__,x, args, kwargs))     return inwapper class User:     info = None     @func     def name(self, name, name1, age):         # return name, name1, age         pass     def Info(self,name,age):         print("我是{},今年{}".format(name,age)) if __name__ == '__main__':     u = User()     u.name("清安","ANAN",age=18) # 2023-03-02 09:19:26,910  root  20 ceshi_test.py 75  inwapper 执行了name,结果是,('清安', 'ANAN'),{'age': 18} # 我是QA,今年18 示例8-伪装 from functools import wraps def timer(value):     def func(fun):         # @wraps(fun)         def inner(*args,**kwargs):             res = fun()             print(value)             print(inner.__name__)             return res         return inner     return func @timer("QA") def run():     pass if __name__ == '__main__':     run() ❝

伪装装饰器,让装饰器函数名称指向运行函数名。

此外还有一些用法,此处就不再阐述,学习完上述的示例后,你是否能自己写出一个像样的装饰器呢?



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3