A usage instance of the Python decorator

  • 2020-04-02 14:22:47
  • OfStack

This article illustrates the use of the Python decorator as an example. Share with you for your reference. Specific analysis is as follows:

1. Closure

Closures are a feature supported by Python that allows functions defined in non-global scope to refer to variables in their outer Spaces, which are called the function's environment variables. The environment variable and this non-global function together form the closure.

def outer(x):
    y = [1,2,3]
    def inner():
        print x
        print y
    return inner
x = 5    # this x Not quoted
f = outer(2)
f()

Print f. __closure__     Function property of successive closure__ stores the function's environment variable def entrance(func):
  = 5       This x is not referenced f = outer(2)f()print f. CLCLP     Function property of successive closure__ stores the function's environment variable def entrance(func):
Both x and y belong to the outer namespace, which is referenced in inner. When the outer exits, the outer namespace no longer exists, but inner maintains the connection to its external variables x and y at the time of its definition.
Program output:
2
[1, 2, 3]
(,)

An decorator is a callable object (a callable), and in Python, functions are objects, and of course callable, so an decorator can be a function, which we calla function decorator.
This callable object takes a function as an argument, closes and returns another function.
Such as:

def entrance(func):
     def inner():
         print "inside function :", func.__name__
         func()
     return inner

 
The entrance is a decorator. It's a function that takes a function func as an argument and returns another function inner.
So why is it called a decorator? Inside the return function inner(), func() is called, and extra operations are done to "decorate" the function func.
How do you use the decorator?

def fun1():
    pass
fun1 = entrance(fun1)
def fun2():
    pass
fun2 = entrance(fun2)

 
The names fun1 and fun2 haven't changed, but they've already "decorated" themselves by calling the function decorator entrance(), which points to another function inner().

The @ operator

Python provides the @ sign, which is essentially what it does above, to re-assign a function name, which is a syntactic trick. So this code up here is equivalent to

@entrance
def fun1():
    pass
@entrance
def fun2():
    pass

 
2. Use of decorators

From this very simple example of intentional construction, you can see what decorator means. If a function needs a function, if the function can be used on many functions, or if the function is not implemented by itself, write a decorator to implement the function.
The decorator entrance, above, decorates a function, and when the function is called, the name of the function is printed.
But the problem is that this decorator is functionally supposed to be able to decorate any function, but if we use it to decorate a function with arguments

 @entrance
 def fun3(x):
     pass

As long as you don't call fun3, these three lines of code won't cause the Python interpreter to report an error, because we already know that it's equivalent to:
def fun3(x):
    pass
fun3 = entrance(fun3)

 
We defined a function called fun3 with arguments, and then pointed fun3 to another function called inner().
 
However, when we use fun3, we definitely use it the way it's defined, passing it an argument.
> > > Fun3 (1)
There's going to be an error, so let's see how the interpreter does that

Traceback (most recent call last):
File "decorator.py", line 23, in www.jb51.net < The module >
Fun3 (1)
TypeError: inner() takes no arguments (1 given)

Of course it's easy to see why this is the case, fun3 is no longer pointing to the function it was defined to, it's now pointing to "inner()", and inner has no arguments, so of course it can go wrong.
So what's the solution?
Modify the definition of inner() so that it can take any number of arguments.

def entrance(func):
     def inner(*args, **kvargs):
         print "inside function : ", func.__name__
         func(*args, **kvargs)
     return inner

Now, you can pass any parameter to inner without error, so the entrance can be used to decorate any function.

3. Write a decorator logger

When a function is called, its name and the actual parameters are logged

def logger(func):
    def inner(*args, **kvargs):
        print  func.__name__, 'called, arguments: ', args, kvargs
        func(*args, **kvargs)
    return inner

I hope this article has helped you with your Python programming.


Related articles: