python装饰器参数转递,我终于弄懂了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”时,该函数已经被修饰,因此您无法进行任何更改。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值