12步简单理解Python的装饰器


  1. 函数

In [24]: def foo():
   ....:     return 1
   ....: 

In [25]: foo()
Out[25]: 1


2.函数的作用域

In [62]: a_string = "This is a global variable"

In [63]: def foo():
   ....:     print locals()
   ....:     
   ....:     

In [64]: print globals()
-------> print(globals())
{''''''''''''''' u'a_string = "This is a global variable"\n', '_oh': {}, 'Out': {}}

In [65]: foo()
{}

In [66]:


3.变量的解析规则

In [75]: a_string = "This is global variable"

In [76]: def foo():
   ....:     print a_string
   ....:     
   ....:     

In [77]: foo()
This is global variable
In [87]: a_string = "This is global variable"

In [88]: def foo():
   ....:     a_string = "test"
   ....:     print locals()
   ....:     
   ....:     

In [89]: foo()
{'a_string': 'test'}

In [90]: a_string
Out[90]: 'This is global variable'



4.变量的生命周期

In [117]: def foo():
   .....:     x = 1
   .....:     
   .....:     

In [118]: foo()

In [119]: print x
--------> print(x)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)

/home/caribbean/<ipython console> in <module>()

NameError: name 'x' is not defined

In [120]:



5.函数的实参和形参  arguments and parameters

python可以允许传递参数给函数,这个参数就是arguments . 函数的参数变量就就是parameter

In [27]: def foo(x):
   ....:     print locals()
   ....:     
   ....:     

In [28]: foo(1)
{'x': 1}
In [64]: def foo(x,y=0):
   ....:     return x -y
   ....: 

In [65]: foo(3,1)
Out[65]: 2

In [66]: foo(3)
Out[66]: 3

In [67]: foo()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/caribbean/<ipython console> in <module>()

TypeError: foo() takes at least 1 argument (0 given)

In [68]: foo(y=1,x=3)
Out[68]: 2



6.嵌套函数

In [73]: def outer():
   ....:     x = 1
   ....:     def inner():
   ....:         print x
   ....:         
   ....:     inner()
   ....:     
   ....:     

In [74]: outer()
1



7.

Functions are first class objects in Python

In [109]: issubclass(int,object)
Out[109]: True

In [110]: def foo():
   .....:     pass
   .....: 

In [111]: foo.__class__
Out[111]: <type 'function'>

In [112]: issubclass(foo.__class__,object)
Out[112]: True
In [119]: def add(x,y):
   .....:     return x + y
   .....: 

In [120]: def sub(x,y):
   .....:     return x - y
   .....: 

In [121]: def apply(func,x,y):
   .....:     return func(x,y)
   .....: 

In [122]: apply(add,2,1)
Out[122]: 3

In [123]: apply(sub,2,1)
Out[123]: 1


函数可以作为参数传递给另一个函数,也可以返回一个函数

In [166]: def outer():
   .....:     def inner():
   .....:         print "Inside inner"
   .....:     return inner
   .....: 

In [167]: foo = outer()

In [168]: foo
Out[168]: <function inner at 0x1d488c0>

In [169]: foo()
Inside inner


8.function closures

In [14]: def outer():
   ....:     x = 1
   ....:     def inner():
   ....:         print x
   ....:     return inner
   ....: 

In [15]: foo = outer()

In [16]: foo.fu
foo.func_closure   foo.func_defaults  foo.func_doc       foo.func_name
foo.func_code      foo.func_dict      foo.func_globals   

In [16]: foo.func_closure
Out[16]: (<cell at 0x1525be8: int object at 0xf9f338>,)



In [24]: def outer(x):
   ....:     def inner():
   ....:         print x
   ....:     return inner
   ....: 

In [25]: print1 = outer(1)

In [26]: print2 = outer(2)

In [27]: print1()
1

In [28]: print2()
2



9.装饰器

A decorator is just a callable that takes a function as an argument and returns a replacement function. 

In [48]: def outer(some_func):
   ....:     def inner():
   ....:         print "before some_func"
   ....:         ret = some_func()
   ....:         return ret + 1
   ....:     return inner
   ....: 

In [49]: 

In [50]: def foo():
   ....:     return 1
   ....: 

In [51]: decorated = outer(foo)

In [52]: decorated()
before some_func
Out[52]: 2
In [55]: foo = outer(foo)

In [56]: foo
Out[56]: <function inner at 0x1516b90>





可以把decorated变量理解成为foo的一个装饰过的版本



In [73]: class Coordinate(object):
   ....:     def __init__(self,x,y):
   ....:         self.x = x
   ....:         self.y = y
   ....:         
   ....:     def __repr__(self):
   ....:         return "Coord: " + str(self.__dict__)
   ....:     
   ....:     

In [74]: def add(a,b):
   ....:     return Coordinate(a.x + b.x,a.y + b.y)
   ....: 

In [75]: def sub(a,b):
   ....:     return Coordinate(a.x - b.x,a.y - b.y)
   ....: 

In [76]: one = Coordinate(100,200)

In [77]: two = Coordinate(300,200)

In [78]: add(one,two)
Out[78]: Coord: {'y': 400, 'x': 400}

In [79]: 

In [80]: one = Coordinate(100,200)

In [81]: two = Coordinate(300,200)

In [82]: three = Coordinate(-100,-100)

In [83]: sub(one,two)
Out[83]: Coord: {'y': 0, 'x': -200}

In [84]: add(one,three)
Out[84]: Coord: {'y': 100, 'x': 0}


In [106]: def wrapper(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)   .....:         ret = func(a,b)
   .....:         if ret.x < 0 or ret.y < 0:
   .....:             ret = Coordinate(ret.x if ret.x > 0 else 0, ret.y if ret.y 
   .....:         return ret
   .....:     return checker
   .....: 

In [107]: add=wrapper(add)

In [108]: sub=wrapper(sub)

In [109]: sub(one,two)
Out[109]: Coord: {'y': 0, 'x': 0}

In [110]: add(one,three)
Out[110]: Coord: {'y': 200, 'x': 100}



10.  @符号应用到一个函数的装饰器上

在以上的例子中

add=wrapper(add)


可以写成

In [142]: @wrapper
   .....: def add(a,b):
   .....:     return Coordinate(a.x + b.x,a.y + b.y)
   .....:



11. *args 和 **kwargs


在以上的例子中,对函数add()和sub()写了一个装饰器wrapper,这两个函数都只带两个参数。如果想要一个装饰器对任何函数都起作用,

In [16]: def one(*args):
   ....:     print args
   ....:     
   ....:     

In [17]: one()
()

In [18]: one(1,2,3)
(1, 2, 3)

In [19]: def two(x,y,*args):
   ....:     print x,y,args
   ....:     
   ....:     

In [20]: two('a','b','c')
a b ('c',)


In [27]: def add(x,y):
   ....:     return x + y
   ....: 

In [28]: lst = [1,2]

In [29]: add(lst[0],lst[1])
Out[29]: 3

In [30]: add(*lst)
Out[30]: 3




* 代表位置参数

** 代表字典和键值对

In [36]: def foo(**kwargs):
   ....:     print kwargs
   ....:     
   ....:     

In [37]: foo()
{}

In [38]: foo(x=1,y=2)
{'y': 2, 'x': 1}


In [44]: dct = { 'x' :1, 'y' :2 }

In [45]: def bar(x,y):
   ....:     return x + y
   ....: 

In [46]: 

In [47]: bar(**dct)
Out[47]: 3





12.

More generic decorators

In [62]: def logger(func):
   ....:     def inner(*args,**kwargs):
   ....:         print "Argument were: %s, %s" % (args,kwargs)
   ....:         return func(*args,**kwargs)
   ....:     return inner
   ....: 

In [63]: @logger
   ....: def foo1(x,y=1):
   ....:     return x * y
   ....: 

In [64]: @logger
   ....: def foo2():
   ....:     return 2
   ....: 

In [65]: foo1(5,4)
Argument were: (5, 4), {}
Out[65]: 20

In [66]: foo1(1)
Argument were: (1,), {}
Out[66]: 1

In [67]: foo2()
Argument were: (), {}
Out[67]: 2









参考资料:

http://www.simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/


你可能感兴趣的:(python)