defmethod_friendly_decorator(method_to_decorate):defwrapper(self,lie): lie = lie -3# 女性福音 :-)returnmethod_to_decorate(self, lie)return wrapperclassLucy(object):def__init__(self): self.age =32@method_friendly_decoratordefsayYourAge(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?
如果想造一个更加通用的,可以同时满足方法和函数的装饰器,用 *args,**kwargs 即可
defa_decorator_passing_arbitrary_arguments(function_to_decorate):# 包装器接受所有参数defa_wrapper_accepting_arbitrary_arguments(*args,**kwargs):print"Do I have args?:"print argsprint kwargs# 现在把*args,**kwargs解包# 如果你不明白什么是解包的话,请查阅:# http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/function_to_decorate(*args, **kwargs)return a_wrapper_accepting_arbitrary_arguments
defdecorator_maker_with_arguments(decorator_arg1,decorator_arg2):print"I make decorators! And I accept arguments:", decorator_arg1, decorator_arg2defmy_decorator(func):# 这里传递参数的能力是借鉴了 closures.# 如果对closures感到困惑可以看看下面这个:# http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-pythonprint"I am the decorator. Somehow you passed me arguments:", decorator_arg1, decorator_arg2# 不要忘了装饰器参数和函数参数!defwrapped(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))returnfunc(function_arg1, function_arg2)return wrappedreturn my_decorator@decorator_maker_with_arguments("Leonard", "Sheldon")defdecorated_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 之后,函数已经被装饰了
于是弄一个通用的装饰器,只要装饰了这个装饰器,自定义的装饰器就可以接收任意的参数了
defdecorator_with_args(decorator_to_enhance):""" 这个函数将被用来作为装饰器. 它必须去装饰要成为装饰器的函数. 休息一下. 它将允许所有的装饰器可以接收任意数量的参数,所以以后你不必为每次都要做这个头疼了. saving you the headache to remember how to do that every time. """# 我们用传递参数的同样技巧.defdecorator_maker(*args,**kwargs):# 我们动态的建立一个只接收一个函数的装饰器,# 但是他能接收来自maker的参数defdecorator_wrapper(func):# 最后我们返回原始的装饰器,毕竟它只是'平常'的函数# 唯一的陷阱:装饰器必须有这个特殊的,否则将不会奏效.returndecorator_to_enhance(func, *args, **kwargs)return decorator_wrapperreturn decorator_maker