简体   繁体   中英

Understanding scope and *args and **kwargs in decorator function

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM