Why is it that the wrapper()
function needs *args
and **kwargs
in the decorator example below?
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))
Aren't the arguments passed to price_with_tax(self, tax_rate_percentage)
already available in the scope of the def currency(f)
function and thus available to the wrapper()
function?
Why can't we just pass f()
right into wrapper()
?
I'm just trying to understand why wrapper()
has *args
and **kwargs
and how both are each getting the arguments passed to price_with_tax(self, tax_rate_percentage)
A wrapper takes a function as an argument and returns another function. In order for that returned function to be as useful as possible (ie, applied to any function or method), it must accept any number of arguments.
Consider what a decorator does. This:
@currency
def price_with_tax(self, tax_rate_percentage):
return price * (1 + (tax_rate_percentage * .01))
Is essentially just shorthand for this:
def price_with_tax(self, tax_rate_percentage):
return price * (1 + (tax_rate_percentage * .01))
price_with_tax = currency(price_with_tax)
That is, price_with_tax
is, ultimately, the return value of currency
, so it should also be a function that takes at least two arguments ( self
and tax_rate_percentage
).
However, @currency
could be used to decorate a lot of other functions which may take different numbers of args and different keyword arguments, so decorators like currency
often take variable arguments to handle all cases.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.