def method_friendly_decorator(method_to_decorate):
def wrapper(self, lie):
lie = lie - 3 # 女性福音 :-)
return method_to_decorate(self, lie)
return wrapper
class Lucy(object):
def __init__(self):
self.age = 32
@method_friendly_decorator
def sayYourAge(self, lie):
print "I am %s, what did you think?" % (self.age + lie)
l = Lucy()
l.sayYourAge(-3)
#输出: I am 26, what did you think?
def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
print "I make decorators! And I accept arguments:", decorator_arg1, decorator_arg2
def my_decorator(func):
# 这里传递参数的能力是借鉴了 closures.
# 如果对closures感到困惑可以看看下面这个:
# http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-python
print "I am the decorator. Somehow you passed me arguments:", decorator_arg1, decorator_arg2
# 不要忘了装饰器参数和函数参数!
def wrapped(function_arg1, function_arg2) :
print ("I am the wrapper around the decorated function.\n"
"I can access all the variables\n"
"\t- from the decorator: {0} {1}\n"
"\t- from the function call: {2} {3}\n"
"Then I can pass them to the decorated function"
.format(decorator_arg1, decorator_arg2,
function_arg1, function_arg2))
return func(function_arg1, function_arg2)
return wrapped
return my_decorator
@decorator_maker_with_arguments("Leonard", "Sheldon")
def decorated_function_with_arguments(function_arg1, function_arg2):
print ("I am the decorated function and only knows about my arguments: {0}"
" {1}".format(function_arg1, function_arg2))
需要记住的是,装饰器只能被调用一次,当 Python 载入脚本后,不可以动态地设置参数了。即运行了 import x 之后,函数已经被装饰了
于是弄一个通用的装饰器,只要装饰了这个装饰器,自定义的装饰器就可以接收任意的参数了
def decorator_with_args(decorator_to_enhance):
"""
这个函数将被用来作为装饰器.
它必须去装饰要成为装饰器的函数.
休息一下.
它将允许所有的装饰器可以接收任意数量的参数,所以以后你不必为每次都要做这个头疼了.
saving you the headache to remember how to do that every time.
"""
# 我们用传递参数的同样技巧.
def decorator_maker(*args, **kwargs):
# 我们动态的建立一个只接收一个函数的装饰器,
# 但是他能接收来自maker的参数
def decorator_wrapper(func):
# 最后我们返回原始的装饰器,毕竟它只是'平常'的函数
# 唯一的陷阱:装饰器必须有这个特殊的,否则将不会奏效.
return decorator_to_enhance(func, *args, **kwargs)
return decorator_wrapper
return decorator_maker