此系列文档:
1. 我终于弄懂了 Python 的装璜器(一)
2. 我终于弄懂了 Python 的装璜器(二)
3. 我终于弄懂了 Python 的装璜器(三)
4. 我终于弄懂了 Python 的装璜器(四)
二、装璜器的高级用法
将参数传递给装璜函数
#它不是黑魔法,只是给包装(wrapper)传递参数:
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print("I got args! Look: {0}, {1}".format(arg1, arg2))
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
#因为当您调用装璜器返回的函数时,调用的包装器(wrapper),将参数传递给被包装器包装的函数
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print("My name is {0} {1}".format(first_name, last_name))
print_full_name("Peter", "Venkman")
# 输入:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
将参数传递给装璜器
对于将参数传递给装璜器自身,您怎么认为?
因为装璜器必须承受一个函数作为参数,所以这可能会有些顺当。
因而,您不能将装璜函数的参数间接传递给装璜器。
在寻求解决方案之前,让咱们写一些揭示:
#装璜器是一般函数
def my_decorator(func):
print("I am an ordinary function")
def wrapper():
print("I am function returned by the decorator")
func()
return wrapper
# 因而,你能够调用它,而不必 "@"
def lazy_function():
print("zzzzzzzz")
decorated_function = my_decorator(lazy_function)
#输入: I am an ordinary function
# 它输入了 "I am an ordinary function", 因为你只是调用了装璜器,而没有调用函数:
# 这里没有什么神奇的中央,应用 '@'
@my_decorator
def lazy_function():
print("zzzzzzzz")
#outputs: I am an ordinary function
后果一样。
my_decorator”被调用了。
因而,当您应用时 @my_decorator,您要通知 Python,通过变量来调用my_decorator 标记了的函数。
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
# 让咱们新建一个装璜器
new_decorator = decorator_maker()
#输入:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
# 让咱们装璜这个函数
def decorated_function():
print("I am the decorated function.")
decorated_function = new_decorator(decorated_function)
#输入:
#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 decorated_function():
print("I am the decorated function.")
decorated_function = decorator_maker()(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.
# Finally:
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.
让咱们把它变的更精简:
@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: {0}, {1}".format(decorator_arg1, decorator_arg2))
def my_decorator(func):
#这里传递的参数是闭包的。
#如果您对封包感到不难受,能够疏忽这点。
print("I am the decorator. Somehow you passed me arguments: {0}, {1}".format(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
记住它:带参数的装璜器,能够将变量作为参数:
c1 = "Penny"
c2 = "Leslie"
@decorator_maker_with_arguments("Leonard", c1)
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(c2, "Howard")
#输入:
#I make decorators! And I accept arguments: Leonard Penny
#I am the decorator. Somehow you passed me arguments: Leonard Penny
#I am the wrapper around the decorated function.
#I can access all the variables
# - from the decorator: Leonard Penny
# - from the function call: Leslie Howard
#Then I can pass them to the decorated function
#I am the decorated function and only know about my arguments: Leslie Howard
如您所见,您能够像任何函数传递参数一样传递参数给装璜器。
您甚至能够依据须要应用 *args, **kwargs。
然而请记住,装璜器 仅被调用 一次 ,仅在 Python 导入脚本时。之后,您将无奈动静设置参数。
当您执行“import x”时,该函数曾经被润饰,因而您无奈进行任何更改。
本文首发于 BigYoung 小站
将参数传递给装璜函数
#它不是黑魔法,只是给包装(wrapper)传递参数:
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print("I got args! Look: {0}, {1}".format(arg1, arg2))
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
#因为当您调用装璜器返回的函数时,调用的包装器(wrapper),将参数传递给被包装器包装的函数
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print("My name is {0} {1}".format(first_name, last_name))
print_full_name("Peter", "Venkman")
# 输入:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
将参数传递给装璜器
对于将参数传递给装璜器自身,您怎么认为?
因为装璜器必须承受一个函数作为参数,所以这可能会有些顺当。
因而,您不能将装璜函数的参数间接传递给装璜器。
在寻求解决方案之前,让咱们写一些揭示:
#装璜器是一般函数
def my_decorator(func):
print("I am an ordinary function")
def wrapper():
print("I am function returned by the decorator")
func()
return wrapper
# 因而,你能够调用它,而不必 "@"
def lazy_function():
print("zzzzzzzz")
decorated_function = my_decorator(lazy_function)
#输入: I am an ordinary function
# 它输入了 "I am an ordinary function", 因为你只是调用了装璜器,而没有调用函数:
# 这里没有什么神奇的中央,应用 '@'
@my_decorator
def lazy_function():
print("zzzzzzzz")
#outputs: I am an ordinary function
后果一样。
my_decorator”被调用了。
因而,当您应用时 @my_decorator,您要通知 Python,通过变量来调用my_decorator 标记了的函数。
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
# 让咱们新建一个装璜器
new_decorator = decorator_maker()
#输入:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
# 让咱们装璜这个函数
def decorated_function():
print("I am the decorated function.")
decorated_function = new_decorator(decorated_function)
#输入:
#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 decorated_function():
print("I am the decorated function.")
decorated_function = decorator_maker()(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.
# Finally:
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.
让咱们把它变的更精简:
@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: {0}, {1}".format(decorator_arg1, decorator_arg2))
def my_decorator(func):
#这里传递的参数是闭包的。
#如果您对封包感到不难受,能够疏忽这点。
print("I am the decorator. Somehow you passed me arguments: {0}, {1}".format(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
记住它:带参数的装璜器,能够将变量作为参数:
c1 = "Penny"
c2 = "Leslie"
@decorator_maker_with_arguments("Leonard", c1)
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(c2, "Howard")
#输入:
#I make decorators! And I accept arguments: Leonard Penny
#I am the decorator. Somehow you passed me arguments: Leonard Penny
#I am the wrapper around the decorated function.
#I can access all the variables
# - from the decorator: Leonard Penny
# - from the function call: Leslie Howard
#Then I can pass them to the decorated function
#I am the decorated function and only know about my arguments: Leslie Howard
如您所见,您能够像任何函数传递参数一样传递参数给装璜器。
您甚至能够依据须要应用 *args, **kwargs。
然而请记住,装璜器 仅被调用 一次 ,仅在 Python 导入脚本时。之后,您将无奈动静设置参数。
当您执行“import x”时,该函数曾经被润饰,因而您无奈进行任何更改。
本文首发于 BigYoung 小站
#它不是黑魔法,只是给包装(wrapper)传递参数:
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print("I got args! Look: {0}, {1}".format(arg1, arg2))
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
#因为当您调用装璜器返回的函数时,调用的包装器(wrapper),将参数传递给被包装器包装的函数
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
print("My name is {0} {1}".format(first_name, last_name))
print_full_name("Peter", "Venkman")
# 输入:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
将参数传递给装璜器
对于将参数传递给装璜器自身,您怎么认为?
因为装璜器必须承受一个函数作为参数,所以这可能会有些顺当。
因而,您不能将装璜函数的参数间接传递给装璜器。
在寻求解决方案之前,让咱们写一些揭示:
#装璜器是一般函数
def my_decorator(func):
print("I am an ordinary function")
def wrapper():
print("I am function returned by the decorator")
func()
return wrapper
# 因而,你能够调用它,而不必 "@"
def lazy_function():
print("zzzzzzzz")
decorated_function = my_decorator(lazy_function)
#输入: I am an ordinary function
# 它输入了 "I am an ordinary function", 因为你只是调用了装璜器,而没有调用函数:
# 这里没有什么神奇的中央,应用 '@'
@my_decorator
def lazy_function():
print("zzzzzzzz")
#outputs: I am an ordinary function
后果一样。
my_decorator”被调用了。
因而,当您应用时 @my_decorator,您要通知 Python,通过变量来调用my_decorator 标记了的函数。
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
# 让咱们新建一个装璜器
new_decorator = decorator_maker()
#输入:
#I make decorators! I am executed only once: when you make me create a decorator.
#As a decorator maker, I return a decorator
# 让咱们装璜这个函数
def decorated_function():
print("I am the decorated function.")
decorated_function = new_decorator(decorated_function)
#输入:
#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 decorated_function():
print("I am the decorated function.")
decorated_function = decorator_maker()(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.
# Finally:
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.
让咱们把它变的更精简:
@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: {0}, {1}".format(decorator_arg1, decorator_arg2))
def my_decorator(func):
#这里传递的参数是闭包的。
#如果您对封包感到不难受,能够疏忽这点。
print("I am the decorator. Somehow you passed me arguments: {0}, {1}".format(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
记住它:带参数的装璜器,能够将变量作为参数:
c1 = "Penny"
c2 = "Leslie"
@decorator_maker_with_arguments("Leonard", c1)
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(c2, "Howard")
#输入:
#I make decorators! And I accept arguments: Leonard Penny
#I am the decorator. Somehow you passed me arguments: Leonard Penny
#I am the wrapper around the decorated function.
#I can access all the variables
# - from the decorator: Leonard Penny
# - from the function call: Leslie Howard
#Then I can pass them to the decorated function
#I am the decorated function and only know about my arguments: Leslie Howard
如您所见,您能够像任何函数传递参数一样传递参数给装璜器。
您甚至能够依据须要应用 *args, **kwargs。
然而请记住,装璜器 仅被调用 一次 ,仅在 Python 导入脚本时。之后,您将无奈动静设置参数。
当您执行“import x”时,该函数曾经被润饰,因而您无奈进行任何更改。
本文首发于 BigYoung 小站