没有包装器的装饰器与函数 - Python
Decorator vs Function without wrapper - Python
我目前正在尝试了解装饰器是什么以及它们的用途。到现在为止,我了解到它们只是将 return 函数作为参数传递的函数,它们的目的是修改函数 w/o 修改原始函数。
我的问题与用于定义它们的经典结构有关。通常你会定义一个装饰器函数,并在其中定义另一个名为 wrapper 的函数,它 return 由装饰器函数编辑。
所以我的问题是,为什么只用一个函数就可以完成包装器,为什么要在装饰器内部创建包装器?这样做会不会更 "pythonic" 减少代码量?
例如下面2段代码:
def country(func):
def wrapper_function():
print("The name of my favorite country is: ")
return func()
return wrapper_function
@country # == fav_country = country(fav)
def fav():
print("Sweden")
fav()
输出:
我最喜欢的国家的名字是:
瑞典
def country(func):
print("The name of my favorite country is: ")
return func
@country # == fav_country = country(fav)
def fav():
print("Sweden")
fav()
输出:
我最喜欢的国家的名字是:
瑞典
你说得对,装饰器就是一个以函数作为参数并返回函数的函数。但是这两个:
def country1(func):
def wrapper_function():
print("The name of my favorite country is: ")
return func()
return wrapper_function
def country2(func):
print("The name of my favorite country is: ")
return func
不等价。考虑
@country1
def fav1():
print("Sweden")
@country2
def fav2():
print("Sweden")
看看你打电话时会发生什么
fav1()
fav1()
fav1()
和
fav2()
fav2()
fav2()
您的 country2
没有修改原始函数,结果 The name of my favorite country is:
在装饰过程中(在函数声明处)仅打印一次。当 country1
改变修饰函数的行为时,您将看到该消息三次。
在您的情况下,不需要包装函数。您没有对传递的参数和 return 参数执行任何操作。
def printall(func):
def inner(*args):
print('Arguments for args: {}'.format(args))
return func(*args)
return inner
@printall
def random_func(*args):
return sum(*args)
a = random_func(2, 2)
例如,如果您希望传递的参数以更高的值开始(有点像添加的偏移量),这将很有用。那么你可以这样做:
def offset(func):
def inner(*args):
args = [arg + 2 for arg in args]
return func(*args) # <-- here it is calling your random_func with modified passed parameters!
return inner
@offset
def random_func(*args):
return sum(*args)
a = random_func(2, 2)
所以当修改传递的参数时,你必须使用包装器来实现。
我目前正在尝试了解装饰器是什么以及它们的用途。到现在为止,我了解到它们只是将 return 函数作为参数传递的函数,它们的目的是修改函数 w/o 修改原始函数。
我的问题与用于定义它们的经典结构有关。通常你会定义一个装饰器函数,并在其中定义另一个名为 wrapper 的函数,它 return 由装饰器函数编辑。
所以我的问题是,为什么只用一个函数就可以完成包装器,为什么要在装饰器内部创建包装器?这样做会不会更 "pythonic" 减少代码量?
例如下面2段代码:
def country(func):
def wrapper_function():
print("The name of my favorite country is: ")
return func()
return wrapper_function
@country # == fav_country = country(fav)
def fav():
print("Sweden")
fav()
输出:
我最喜欢的国家的名字是:
瑞典
def country(func):
print("The name of my favorite country is: ")
return func
@country # == fav_country = country(fav)
def fav():
print("Sweden")
fav()
输出: 我最喜欢的国家的名字是:
瑞典
你说得对,装饰器就是一个以函数作为参数并返回函数的函数。但是这两个:
def country1(func):
def wrapper_function():
print("The name of my favorite country is: ")
return func()
return wrapper_function
def country2(func):
print("The name of my favorite country is: ")
return func
不等价。考虑
@country1
def fav1():
print("Sweden")
@country2
def fav2():
print("Sweden")
看看你打电话时会发生什么
fav1()
fav1()
fav1()
和
fav2()
fav2()
fav2()
您的 country2
没有修改原始函数,结果 The name of my favorite country is:
在装饰过程中(在函数声明处)仅打印一次。当 country1
改变修饰函数的行为时,您将看到该消息三次。
在您的情况下,不需要包装函数。您没有对传递的参数和 return 参数执行任何操作。
def printall(func):
def inner(*args):
print('Arguments for args: {}'.format(args))
return func(*args)
return inner
@printall
def random_func(*args):
return sum(*args)
a = random_func(2, 2)
例如,如果您希望传递的参数以更高的值开始(有点像添加的偏移量),这将很有用。那么你可以这样做:
def offset(func):
def inner(*args):
args = [arg + 2 for arg in args]
return func(*args) # <-- here it is calling your random_func with modified passed parameters!
return inner
@offset
def random_func(*args):
return sum(*args)
a = random_func(2, 2)
所以当修改传递的参数时,你必须使用包装器来实现。