vlambda博客
学习文章列表

我终于弄懂了Python的装饰器(二)

↑ 关注 + 星标 ~ 从此不迷路,后台回复礼包】送你Python自学资料

BigYoung小站推荐搜索
Django
Python
Windows
Nas


此系列文档:

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_argumentsdef 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_decoratordef 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”时,该函数已经被修饰,因此您无法进行任何更改。



免费福利

1





2


3


猜你喜欢

2. 
3. 


喜欢就点个在看再走吧