了解装饰器函数中的作用域和 *args 和 **kwargs
Posted
技术标签:
【中文标题】了解装饰器函数中的作用域和 *args 和 **kwargs【英文标题】:Understanding scope and *args and **kwargs in decorator function 【发布时间】:2016-04-20 13:43:30 【问题描述】:为什么在下面的装饰器示例中wrapper()
函数需要*args
和**kwargs
?
def currency(f):
def wrapper(*args, **kwargs):
return '$' + str(f(*args, **kwargs))
return wrapper
class Product(db.Model):
name = db.StringColumn
price = db.FloatColumn
@currency
def price_with_tax(self, tax_rate_percentage):
"""Return the price with *tax_rate_percentage* applied.
*tax_rate_percentage* is the tax rate expressed as a float, like "7.0"
for a 7% tax rate."""
return price * (1 + (tax_rate_percentage * .01))
传递给price_with_tax(self, tax_rate_percentage)
的参数不是已经在def currency(f)
函数的范围内可用,因此对wrapper()
函数可用吗?
为什么我们不能直接将f()
传递给wrapper()
?
我只是想了解为什么 wrapper()
有 *args
和 **kwargs
以及两者如何将参数传递给 price_with_tax(self, tax_rate_percentage)
【问题讨论】:
【参考方案1】:包装器接受一个函数作为参数并返回另一个函数。为了使返回的函数尽可能有用(即应用于任何函数或方法),它必须接受任意数量的参数。
考虑一下装饰器的作用。这个:
@currency
def price_with_tax(self, tax_rate_percentage):
return price * (1 + (tax_rate_percentage * .01))
本质上只是这个的简写:
def price_with_tax(self, tax_rate_percentage):
return price * (1 + (tax_rate_percentage * .01))
price_with_tax = currency(price_with_tax)
也就是说,price_with_tax
最终是currency
的返回值,所以它也应该是一个至少接受两个参数(self
和tax_rate_percentage
)的函数。
不过,@currency
可用于装饰许多其他可能采用不同数量的 args 和不同关键字参数的函数,因此像 currency
这样的装饰器通常采用可变参数来处理所有情况。
【讨论】:
以上是关于了解装饰器函数中的作用域和 *args 和 **kwargs的主要内容,如果未能解决你的问题,请参考以下文章