Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1745608
  • 博文数量: 335
  • 博客积分: 4690
  • 博客等级: 上校
  • 技术积分: 4341
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-08 21:38
个人简介

无聊之人--除了技术,还是技术,你懂得

文章分类

全部博文(335)

文章存档

2016年(29)

2015年(18)

2014年(7)

2013年(86)

2012年(90)

2011年(105)

分类: Python/Ruby

2013-08-14 21:06:36


作者的思路清晰,讲解很到位,原文地址: 
http://www.cnblogs.com/fortwo/archive/2013/05/16/3081588.html
1.最简单的函数
复制代码
'''示例1:最简单的函数,调用两次''' def f(): print('in f()')

f()
f()
复制代码

运行结果:

复制代码
in f() in f()
复制代码

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

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

f()
f()
复制代码

运行结果:

复制代码
in f()
used time: 0.017538812265457945 in f()
used time: 0.007859906695771732
复制代码

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

3.定义新函数

复制代码
''''示例3:定义一个函数timeit,将f引用传递给它,然后在timeit中调用f并计时。
这样就不用每次想查看某个函数的执行时间,修改其函数定义了''' import time def 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.05688170348089686 in 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 wrapper def f(): print('in f()')

f = timeit(f)
f()
f()
复制代码

运行结果:

复制代码
in f()
used time: 0.020904102006571737 in f()
used time: 0.003204015169534828
复制代码

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

5.使用@装饰函数

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

@timeit def f(): print('in f()')

f()
f()
复制代码

运行结果:

复制代码
in f()
used time: 0.026976211190267118 in 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 method
This is a class method of <class '__main__.MyClass'> This is a static method
This is a class method of <class '__main__.MyClass'>
复制代码

7.functools模块

functools模块提供了2个装饰器

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

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

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

@timeit def f(): print('in f()')


f()
f() print(f.__name__)
复制代码

运行结果:

复制代码
in f()
used time: 0.023279052418693102 in f()
used time: 0.004277017846773756 wrapper
复制代码

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

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

例如:

复制代码
'''示例7: functools.wraps装饰器''' import time import functools def 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)" @timeit def f(): print('in f()')

f()
f() print(f.__name__)
复制代码

运行结果:

复制代码
in f()
used time: 0.009993350463016054 in f()
used time: 0.004484891854864229 f
复制代码

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

复制代码
in f()
used time: 0.00913592083120428 in f()
used time: 0.004698438837834367 wrapper
复制代码

 

(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__ = opname 29 opfunc.__doc__ = getattr(int, opname).__doc__ 30  setattr(cls, opname, opfunc) 31 return cls
复制代码
阅读(1542) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~