Decorator is an advanced Python syntax. The decorator Can process a function, method, or class. Next, this article will introduce you to the basics of python decorator. If you are interested in the knowledge of python decorator, learning decorator is a high-level Python syntax. The decorator Can process a function, method, or class. In Python, we have multiple methods to process functions and classes. For example, in the Python closure, we can see the function object as the return result of a function. Compared with other methods, the decorator has simple syntax and high code readability. Therefore, the decorator is widely used in Python projects.
The previously introduced decorator syntax quickly. Here, we will go deep into the internal working mechanism of the decorator to introduce in more detail the content of the decorator, and learn more advanced syntaxes for writing new decorators.
What is a decoration device?
Decoration is a way to specify code management for functions and classes. The Python annotator is presented in two forms:
[1] The function annotator rebinds the name when defining a function. It provides a logic layer for managing functions and methods or subsequent calls to them.
[2] The class decorators rebind names when defining classes, provide a logic layer for management, or manage the instances they are subsequently called.
In short, the decorator provides a method to insert automatically Running code at the end of the function and class definition statements-for the function decorator, at the end of def; for the class decorator, at the end of the class. Such code can assume different roles.
The decorator provides a bit of information related to code maintainability and aesthetics. In addition, as a structural tool, the decorator naturally promotes code encapsulation, which reduces redundancy and makes the future easier.
Function decorators
By running another function at the end of the def statement of a function, the initial function name is rebound to the result.
Usage
The decorator is written in a line next to the def statement that defines a function or method, and it is composed of the @ symbol and a reference to the meta function immediately following it-this is a function that manages another function (or other callable objects ).
In encoding, the function annotator automatically uses the following syntax:
@decorator def F(arg): ... F(99)
Ing to this peering form:
def F(arg): ... F = decorator(F) F(99)
The decorator here is a single-parameter callable object that returns a callable object with the same number of parameters as F.
When the F function is subsequently called, it automatically calls the objects returned by the decorator.
In other words, the decoration Actually maps the first line as the second line (although the ornament only runs once during decoration)
fun(6,7) decorator(func)(6,7)
This automatic name rebinding also explains the reason for the previously introduced static methods and the property modifier Syntax:
class C: @staticmethod def meth(...):... @property def name(self):...
Implementation
The decorator itself returns the callable object of the callable object. In fact, it can be any type of callable object and return any type of callable object: Any combination of functions and classes can be used, although some combinations are more suitable for specific backgrounds.
There is a common encoding mode-the decorator returns a package that keeps the original function in a closed scope:
Def decorator (F): def wrapper (* args): # Use F and * args # Call the original F (* args) return wrapper @ decorator def func (x, y) :... func (6, 7)
When the name func is called later, it does call the Package function returned by the decorator; then the package function may run the original func, because it can still be used in a closed scope.
To do the same thing for the class, we can reload the call operation:
Class decorator: def _ init _ (self, func): self. func = func def _ call _ (self, * args): # Use self. func AND args # self. func (* args) calls the initial func @ decorator def func (x, y ):... func (6, 7)
However, it should be noted that in the class-based code, it is effective for intercepting simple functions, but it is not very effective when applied to class method functions:
Example:
Class decorator: def _ init _ (self, func): self. func = func def _ call _ (self, * args): # call self. func (* args) fails because class C: @ decorator def method (self, x, y) cannot be passed in the C instance parameter ):...
At this time, the decoration method is rebound to a class method instead of a simple function, which brings about the problem, when method _ call _ of the decorator is subsequently run, the self accepts the decorator class instance, and the class C instance does not contain a * args.
At this time, the nested function substitution method works better:
def decorator: def warpper(*args): # ... return wrapper @decorator def func(x,y): ... func(6,7) class C: @decorator def method(self,x,y): ... x = C() x.method(6,7)
Class decorator
The class decorator and function decorator use the same syntax and very similar encoding methods. The class decorator is a management method, or uses the additional logic of the Instance created by the management or extension class to wrap the instance construction call.
Usage
Assume that the class decorator returns a single-Parameter Function of the callable object. The syntax of the class decorator is:
@decorator class C: ... x = C(99)
Equivalent to the following syntax:
class C: ... C = decorator(C) x = C(99)
The direct effect is that an instance will be created when you call the class name. This instance will trigger the callable object returned by the decorator, instead of calling the original class itself.
Implementation
The callable object returned by the class decorator. Generally, a new instance of the original class is created and returned, and the interface management is extended in some way. For example, the following instance inserts an object to intercept undefined attributes of a class instance:
Def decorator (cls): class Wrapper: def _ init _ (self, * args): self. wrapped = cls (* args) def _ getattr _ (self, name): return getattr (self. wrapped, name) return Wrapper @ decorator class C: # C = decorator (C) def _ init _ (self, x, y): # Run by Wrapper. _ init _ self. attr = 'spam' x = C (6, 7) # equivalent to Wrapper (6, 7) print (x. attr)
In this example, the modifier rebinds the class name to another class, which maintains the original class in a closed scope.
Like a function decorator, a class decorator can usually be written as a "Factory" function that creates and returns callable objects.
Decorator nesting
Sometimes, a decorator is not enough. The decorator syntax allows us to add multiple layers of the packer logic to a decorator function or method. The syntax of the decorator in this form is:
@A @B @C def f(...): ...
The conversion is as follows:
def f(...): ... f = A(B(C(f)))
Here, the initial function is passed through three different decorators, each of which processes the previous result.
Decorator Parameters
The function decorator and class decorator both accept the following parameters:
@decorator(A,B) def F(arg): ... F(99)
Automatically maps to its peering form:
def F(arg): ... F = decorator(A,B)(F) F(99)
The modifier parameters are parsed before decoration, and they are usually used to maintain state information for subsequent calls. For example, the decorator function in this example may take the following form:
Def decorator (A, B): # Save or use A and B def actualDecorator (F): # Save or use the function F # return A callable object return callable return actualDecorator
Above, this is the basic knowledge of the decorative device, next I will learn to write my own decorative device.