博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python装饰器学习
阅读量:5881 次
发布时间:2019-06-19

本文共 5400 字,大约阅读时间需要 18 分钟。

1.最简单的函数

'''示例1:最简单的函数,调用两次'''def f():    print('in f()')f()f()

运行结果:

in f()in f()

2.最简单函数,添加额外功能

'''示例2:最简单函数,添加功能:查看程序的执行时间'''import timedef f():    start = time.clock()    print('in f()')    end = time.clock()    print('used time:', end - start)f()f()

运行结果:

in f()used time: 0.017538812265457945in f()used time: 0.007859906695771732

问题出现了,如果又想查看另一个函数的执行时间,怎么办?可以复制上述新增的代码到那个需要查看的函数中,但是这样做的话代码就可能会出现重复。下面的办法就避免了代码的重复。

3.定义新函数

''''示例3:定义一个函数timeit,将f引用传递给它,然后在timeit中调用f并计时。这样就不用每次想查看某个函数的执行时间,修改其函数定义了'''import timedef timeit(func):    start = time.clock()    func()    end = time.clock()    print('used time:', end - start)def f():    print('in f()')timeit(f)timeit(f)

运行结果:

in f()used time: 0.05688170348089686in f()used time: 0.0030139705110661524

这里还是有点问题:如果此前f函数在N出被调用,此时就不得不修改N处的调用代码。解决办法见下面的方法。

4.装饰器

不修改f函数的调用代码,但是想要在调用f时产生调用timeit(f)。

'''示例4:装饰函数f = timeit(f)'''import time# 定义一个计时器,传入一个函数,返回另一个附加了计时功能的函数def timeit(func):    # 定义一个内嵌的包装函数,给传入的函数加上计时功能    def wrapper():        start = time.clock()        func()        end = time.clock()        print('used time:', end - start)    # 将包装后的函数返回    return wrapperdef f():    print('in f()')f = timeit(f)f()f()

运行结果:

in f()used time: 0.020904102006571737in f()used time: 0.003204015169534828

装饰器的作用:就是为已存在的的对象添加额外的功能。

5.使用@装饰函数

'''示例5:使用@装饰函数,相当于"f = timeit(f)"'''import timedef timeit(func):    def wrapper():        start = time.clock()        func()        end = time.clock()        print('used time:', end - start)    return wrapper@timeitdef f():    print('in f()')f()f()

运行结果:

in f()used time: 0.026976211190267118in f()used time: 0.00859293609272234

6.内置装饰器

内置装饰器有3个:

(1)staticmethod:将类的实例方法变成静态方法

(2)classmethod:将类的实例方法变成类方法

(3)property:将类的实例方法变成类属性

'''示例6:静态方法和类方法的使用'''class MyClass(object):        @staticmethod    def smeth():        print('This is a static method')    @classmethod    def cmeth(cls):        print('This is a class method of', cls)MyClass.smeth()MyClass.cmeth()m = MyClass()m.smeth()m.cmeth()

运行结果:

This is a static methodThis is a class method of 
This is a static methodThis is a class method of

7.functools模块

functools模块提供了2个装饰器

(1)wraps(wrapped[, assigned][, updated])

函数的特殊属性如函数名__file__,在被装饰后,函数名f会变成包装函数的名字wrapper。例如:在实例5的基础上添加一条打印__file__的语句:

'''示例5:使用@装饰函数,相当于"f = timeit(f)"'''import timedef timeit(func):    def wrapper():        start = time.clock()        func()        end = time.clock()        print('used time:', end - start)    return wrapper@timeitdef f():    print('in f()')f()f()print(f.__name__)

运行结果:

in f()used time: 0.023279052418693102in f()used time: 0.004277017846773756wrapper

由结果可知:看到f.__name__的值是wrapper。

functools模块中的wraps装饰器可以解决这个问题,它能够将装饰过的函数的特殊属性保留。

例如:

'''示例7: functools.wraps装饰器'''import timeimport functoolsdef timeit(func):    #"@functools.wraps(func)"等价于:"wrapper = functools.wraps(func)(wrapper)"    @functools.wraps(func)    def wrapper():        start = time.clock()        func()        end = time.clock()        print('used time:', end - start)    return wrapper#"@timeit"等价于:"f = timeit(f)"@timeitdef f():    print('in f()')f()f()print(f.__name__)

运行结果:

in f()used time: 0.009993350463016054in f()used time: 0.004484891854864229f

如果注释掉@functools.wraps(func)的结果:

in f()used time: 0.00913592083120428in f()used time: 0.004698438837834367wrapper

 

(2)total_ordering(cls)

这个装饰器在特定场合有一定的用处。它的作用是为了实现至少__lt__,__le__,__gt__,__ge__其中的一个类加上其他的比较方法,这是一个类的装饰器。具体查看其源码functools.py中的实现。

1 ################################################################################ 2 ### total_ordering class decorator 3 ################################################################################ 4  5 def total_ordering(cls): 6     """Class decorator that fills in missing ordering methods""" 7     convert = { 8         '__lt__': [('__gt__', lambda self, other: not (self < other or self == other)), 9                    ('__le__', lambda self, other: self < other or self == other),10                    ('__ge__', lambda self, other: not self < other)],11         '__le__': [('__ge__', lambda self, other: not self <= other or self == other),12                    ('__lt__', lambda self, other: self <= other and not self == other),13                    ('__gt__', lambda self, other: not self <= other)],14         '__gt__': [('__lt__', lambda self, other: not (self > other or self == other)),15                    ('__ge__', lambda self, other: self > other or self == other),16                    ('__le__', lambda self, other: not self > other)],17         '__ge__': [('__le__', lambda self, other: (not self >= other) or self == other),18                    ('__gt__', lambda self, other: self >= other and not self == other),19                    ('__lt__', lambda self, other: not self >= other)]20     }21     # Find user-defined comparisons (not those inherited from object).22     roots = [op for op in convert if getattr(cls, op, None) is not getattr(object, op, None)]23     if not roots:24         raise ValueError('must define at least one ordering operation: < > <= >=')25     root = max(roots)       # prefer __lt__ to __le__ to __gt__ to __ge__26     for opname, opfunc in convert[root]:27         if opname not in roots:28             opfunc.__name__ = opname29             opfunc.__doc__ = getattr(int, opname).__doc__30             setattr(cls, opname, opfunc)31     return cls

 

 

 

转载于:https://www.cnblogs.com/fortwo/archive/2013/05/16/3081588.html

你可能感兴趣的文章
Rackspace: IT与业务的融合是一门艺术
查看>>
雅虎高管称移动2.0将于今年年底出现
查看>>
八一八聊天机器人的那些事儿
查看>>
能理解聊天记录的微信机器人 (四)
查看>>
中软国际抢占医疗大数据风口
查看>>
RDS SQL Server - 专题分享 - 巧用执行计划缓存之执行计划编译
查看>>
《C++语言入门经典》一2.6 表达式
查看>>
个人信息泄露 一条短信盗走积蓄
查看>>
《MonoTouch开发实践指南》一1.1 搭建开发环境
查看>>
如何做好ERP项目经理?
查看>>
Alphabet财报让华尔街兴奋:股价还会涨 买买买
查看>>
数据专家必知必会的7款Python工具
查看>>
关于数据分析,管理者常犯的4个错误
查看>>
A Neural Probabilistic Language Model
查看>>
如何使用网络视频服务器的权限管理
查看>>
WannaCry警示:学会检测和减轻云端恶意内容
查看>>
光纤将在5G发展中发挥关键作用
查看>>
思博伦推出Temeva平台:“云中测试”成为可能
查看>>
移动CRM风起云涌 千亿级市场显现
查看>>
韩国SK电讯宣布成功研发量子中继器
查看>>