参考
https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html
简单介绍下
- 装饰器就是把其他函数作为参数的函数
def my_shiny_new_decorator(a_function_to_decorate):
def the_wrapper_around_the_original_function():
# 把要在原始函数被调用前的代码放在这里
print "Before the function ru先简单ns"
# 调用原始函数(用括号)
a_function_to_decorate()
# 把要在原始函数调用后的代码放在这里
print "After the function runs"
return the_wrapper_around_the_original_function
- 装饰器真实面纱
@my_shiny_new_decorator
def another_stand_alone_function():
print "Leave me alone"
another_stand_alone_function()
#输出:
#Before the function runs
#Leave me alone
#After the function runs
就这么简单.@decorator就是下面的简写:
another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)
- 装饰器里传入参数
# 这不是什么黑魔法,你只需要让包装器传递参数:
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print "I got args! Look:", arg1, arg2
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
# 当你调用装饰器返回的函数时,也就调用了包装器,把参数传入包装器里,
# 它将把参数传递给被装饰的函数里.
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print "My name is", first_name, last_name
print_full_name("Peter", "Venkman")
# 输出:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
- 装饰方法
在Python里方法和函数几乎一样.唯一的区别就是方法的第一个参数是一个当前对象的(self)
来点刺激的
把参数传递给装饰器
- 先来看个
@decorator_maker()
例子(相当于decorated_function = decorator_maker()(decorated_function)
)
def decorator_maker():
print "I make decorators! I am executed only once: "+\
"when you make me create a decorator."
def my_decorator(func):
print "I am a decorator! I am executed only when you decorate a function."
def wrapped():
print ("I am the wrapper around the decorated function. "
"I am called when you call the decorated function. "
"As the wrapper, I return the RESULT of the decorated function.")
return func()
print "As the decorator, I return the wrapped function."
return wrapped
print "As a decorator maker, I return a decorator"
return my_decorator
@decorator_maker()
def decorated_function():
print "I am the decorated function."
#输出:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
#I am a decorator! I am executed only when you decorate a function.
#As the decorator, I return the wrapped function.
#最终:
decorated_function()
#输出:
#I am the wrapper around the decorated function. I am called when you call the decorated function.
#As the wrapper, I return the RESULT of the decorated function.
#I am the decorated function.
所以如果我们在函数运行过程中动态生成装饰器,就可以把参数传递给函数
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))
decorated_function_with_arguments("Rajesh", "Howard")
#输出:
#I make decorators! And I accept arguments: Leonard Sheldon
#I am the decorator. Somehow you passed me arguments: Leonard Sheldon
#I am the wrapper around the decorated function.
#I can access all the variables
# - from the decorator: Leonard Sheldon
# - from the function call: Rajesh Howard
#Then I can pass them to the decorated function
#I am the decorated function and only knows about my arguments: Rajesh Howard
但是一定要记住了装饰器只能被调用一次.当Python载入脚本后,你不可以动态的设置参数了.当你运行import x,函数已经被装饰,所以你什么都不能动了
最后来一个屌爆的线程安全单实例装饰器
def singleton(cls):
instance = cls()
instance.__call__ = lambda: instance
return instance
#
# Sample use
#
@singleton
class Highlander:
x = 100
# Of course you can have any attributes or methods you like.
Highlander() is Highlander() is Highlander #=> True
id(Highlander()) == id(Highlander) #=> True
Highlander().x == Highlander.x == 100 #=> True
Highlander.x = 50
Highlander().x == Highlander.x == 50 #=> True
- 在定义class Highlander的时候已经执行完所有singleton装饰器中的代码,得到了一个instance,所以这之后所有对Highlander的调用实际上是在调用instance的call 方法。
- 我们通过lambda函数定义了call方法让它始终返回instance,因此Highlander()和Highlander都返回instance
- 同时由于在类定义代码执行时就已经创建了instance,所以后续不论是多线程还是单线程,在调用Highlander时都是在调用instance的call方法,也就无需同步了。
最后我想说的是这种方法简直碉堡了~~~