最後更新: 2015-02-24
DOC:
http://thecodeship.com/patterns/guide-to-python-function-decorators/
https://pythonconquerstheuniverse.wordpress.com/2012/04/29/python-decora...
https://wiki.python.org/moin/PythonDecoratorLibrary
什麼是 "@"
* decorators = macros
* decorators = Nested functions
* outer is a constructor for inner
Nested functions
def outer(): x = 1 def inner(): print x inner() # 2 outer()
# you can pass functions to functions as arguments
def add(x, y): return x + y def sub(x, y): return x - y def apply(func, x, y): return func(x, y) apply(add, 2, 1) # 3
# return functions from functions as return values!
def outer(): def inner(): print "Inside inner" return inner foo = outer() foo <function inner at 0x...> foo() Inside inner
function closures
inner functions defined in non-global scope remember what their enclosing namespaces looked like at definition time.
def outer():
x = 1
def inner():
print x # 1
return inner
foo = outer()
outer is a constructor for inner with x acting like a private member variable.
decorators
returns a modified version of a function (add)
- it does something useful by checking and normalizing the input parameters(wrapper)
class Coordinate(object): def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return "Coord: " + str(self.__dict__) def wrapper(func): def checker(a, b): # 1 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 > 0 else 0) return ret return checker # "@" 有類似 "add = wrapper(add)" 的作用 @wrapper def add(a, b): return Coordinate(a.x + b.x, a.y + b.y)
"@" 的作用
* Python just adds some syntactic sugar to make what is going on very explicit.
* "@" 這寫法有 "makes our code cleaner" 效果
*args **kwargs 與 "@"
def logger(func):
def inner(*args, **kwargs):
print "Arguments were: %s, %s" % (args, kwargs)
return func(*args, **kwargs)
return inner
@logger
def foo1(x, y=2):
return x * y
print foo1(5)