部分参考了这篇文章,像这篇文章的作者致敬!
http://python.jobbole.com/85056/
本文主供自我学习之用,发表在这里仅希望为其他学习者做一点微小的贡献,难免会有错误或不周。欢迎大家指正。
装饰器是一个以函数作为参数并返回一个替换函数的可执行函数。它其实是一种闭包的应用。
理解起来有一定困难,我们一步一步的走:
第一阶段——最简单的装饰器:
>>>def outer(some_func):
def inner():
print '------------------'
return some_func #注意到some_func没有括号
return inner
>>>def fun():
return 1
>>>d=outer(fun)
>>>d()
------------------
>>>def outer(some_func):
def inner():
print '------------------'
return some_func()
return inner
>>>d=outer(fun)
>>>
>>>d()
------------------
1
第二阶段———带一点变量:
>>>def outer(some_func):
def inner(x):
print '------------------'
return some_func(x)
return inner
>>>def fun(x):
print x
>>>d=outer(fun)
>>>d(2)
------------------
2
>>> fun=outer(fun)
>>> fun(2)
------------------
2
由此可见,函数被定义后内层函数就取代了外层函数。这点切记。
加入
>>> fun=outer(fun)
这条语句后会使fun函数彻底变为装饰版。很有意思。
第三阶段———:小试牛刀
>>> class Coordinate(object): #存储坐标的类
def __init__(self,x,y):
self.x=x
self.y=y
def __repr__(self): #打印坐标
return "coord:"+str(self.__dict__)
>>>def add(a,b):
return Coordinate(a.x+b.x,a.y+b.y)
>>>def sun(a,b):
return Coordinate(a.x-b.x,a.y-b.y)
>>>one=Coordinate(100,200)
>>> one
coord:{'y': 200, 'x': 100}
>>>two=Coordinate(300,200)
>>>add(one,two)
coord:{'y':400, 'x': 400}
>>>sun(one,two)
coord:{'y':0, 'x': -200}
>>> def check(func): #一个装饰器,使所有负数坐标归零
def checker(a,b):
if a.x<0 or a.y<0:
a=Coordinate(a.x if a.x>0 else 0,a.y if a.y>0 else 0)
if b.x<0 or b.y<0:
b=Coordinate(b.x if b.x>0 else 0,b.y if b.y>0 else 0)
rea=func(a,b)
if rea.x<0 or rea.y<0:
rea=Coordinate(rea.x if rea.x>0 else 0,rea.y if rea.y<0else 0)
return rea
return checker
>>>add=check(add)
>>>sun=check(sun)
>>>sun(one,two)
coord:{'y':0, 'x': 0}
第四阶段————@的应用
在函数定义前加一个@装饰器名 可以实现对函数的包装。举个小小的例子:
>>> def test(func):
def inner(x):
print '+++++++++++++++++++'
func(x)
print '+++++++++++++++++++'
return inner
>>> def lin(x):
for t in range(2*x-1):
if t print (x-1-t)*' '+(t*2+1)*'@' else: print (t-x+1)*' '+(4*x-2*t-3)*'@' 看这个函数,可以打印棱形: >>>lin(3) @ @@@ @@@@@ @@@ @ 我们用装饰器对它进行装饰: >>> t=test(lin) >>> t(3) +++++++++++++++++++ @ @@@ @@@@@ @@@ @ +++++++++++++++++++ 但是我们可以用@对函数直接进行装饰: >>> @test def lin(x): for t in range(2*x-1): if t print (x-1-t)*' '+(t*2+1)*'@' else: print (t-x+1)*' '+(4*x-2*t-3)*'@' >>> lin(3) +++++++++++++++++++ @ @@@ @@@@@ @@@ @ +++++++++++++++++++ 第五阶段————适用任何函数的装饰器: 我们可以用收集参数的方式作出适用于多个参数的装饰器。 装饰器修改如下: def test(func): def inner(*x): print '+++++++++++++++++++' func(*x) print '+++++++++++++++++++' return inner 用add函数测试它: add(2,3) +++++++++++++++++++ 5 +++++++++++++++++++