python装饰器简述(python2.7)

部分参考了这篇文章,像这篇文章的作者致敬!

 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()

------------------

<function fun at 0x106366140>                #直接 return函数名会返回函数的地址

>>>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<x:

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<x:

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

+++++++++++++++++++



猜你喜欢

转载自blog.csdn.net/shadowfox_/article/details/79438234