Introduction to Python Decorators __python

Source: Internet
Author: User
Tags aop closure function definition in python

http://blog.csdn.net/beckel/article/details/4072886

I expect it to be one of the most important features of Python. The problem is that all the articles I've seen that introduce decorators are easy to confuse. So I'm going to correct straight here.

(This series of articles will be entered into open source category Books Python3 mode and usage)

decorators vs. decorator Mode

First of all, you have to understand that using the word "decorator" is a very prudent decision, because it may be associated with the idea

Design Patterns (designing pattern) a book in the decorator mode. From a certain point of view may be other words also apply to this feature, but "decorator" is still the choice.

You can actually use the Python decorators to implement the decorator model, but it's much more powerful than that. I think the closest thing to the Python decorators is the macro (macros).

The origin of the macro

The history of macros is not short, but most people are probably the preprocessing macros that use C. The problem with macros in C is: (1) They belong to another language (not C); (2) Their behavior is sometimes bizarre. And often inconsistent with the rest of C's behavior.

Both Java and C # have joined the annotations mechanism, which allows users to annotate program variables. Their problem is: (1) in order to achieve something, you sometimes have to endure all aspects of "discipline", and (2) annotation's characteristics are limited by the innate normative provisions of these languages (Martin Fowler genteel called "orientation").

In addition, many C + + programmers (including me) have experienced the generation of C + + templates, and some of the use of this and macro-similar features.

Many other languages have macros. Although I don't know much about it, I'm sure Python decorators and Lisp macros are Briber in their ability.

Why use Macros

I think, from a conservative point of view, the role of macros in programming languages is to provide a way to modify program variables. This is also the work of decorators in Python-they modify the function, and if the class decorators, it is the entire classes. This is why they often provide a simpler choice for metaclasses (the Meta Class).

The main failure of the self-correcting methods in most languages is that they are too restrictive and require a different language (I am not saying that Java annotations is honed to make a distinctive annotation, even if it includes "another language").

Python is Fowler into the "Authorization (enabling)" Language, so if you want to implement a fix, why create a language that is different or more restrictive. Why not use Python itself? This is precisely the mission of Python decorators.

Use of decorators

Decorators allows code to be embedded or modified in functions and classes. This sounds like Java's aspect-oriented programming (AOP, aspect-oriented programming), right. In addition, the former is simpler and more powerful. For example, suppose you want to do something at the entrance and exit of a function (such as doing some security, tracking, and locking-all AOP standard variables). Use the decorators implementation code as follows:

@entryExit

def func1 ():

print "Inside Func1 ()"

 

@entryExit

def func2 ():

print "Inside Func2 ()"

' @ ' indicates the Decorator program.

function Decorators

A function decorators is used for a function definition, which is in a row before the function definition. For example:

@myDecorator

def afunction ():

print "Inside Afunction"

When the compiler passes this code, afunction () is compiled and passed the result function object to the Mydecorator code, which creates a class function object and replaces the original afunction ().

What does the Mydecorator code look like. Most introductory examples are given as functions, but I find it easier and more powerful to understand decorators using classes rather than functions for the decoration mechanism.

The only constraint to the object returned by decorator is that it can be used as a function-meaning that it must be callable. Therefore, any class used as a decorators must implement __call__.

What should decorator do? It can do anything, but you often expect to be able to use the original function code in some places. In fact, there is no need for this:

class Mydecorator (object):

 

def __init__ (self, f):

print "Inside mydecorator.__init__ ()"

f () # Prove that function definition has completed

 

def __call__ (self):

print "Inside mydecorator.__call__ ()"

 

@myDecorator

def afunction ():

print "Inside Afunction ()"

 

print "Finished decorating afunction ()"

 

afunction ()

When you run this piece of code, you see:

inside mydecorator.__init__ ()

inside Afunction ()

finished decorating afunction ()

inside mydecorator.__call__ ()

Note that the Mydecorator constructor (constructor) is executed at the decoration of the function. Since we can call F () inside the __init__ (), it means that f () was created before the call to decorator. Also note that the decorator constructor receives the decorated function object. You will get the function object in the constructor and then use it in the __call__ () method (when using the class, the decoration and the call are two distinct phases, which is why I say it's simpler and more powerful).

When decorated calls Afunction (), it behaves differently: the mydecorator.__call__ () method is no longer invoked with the original code. The reason is that the decoration process replaces the decoration result with the original function--in our case, the Mydecorator object replaces the afunction. In fact, before you join decorators, you need to write very obscure code to achieve the same effect:

def foo (): Pass

foo = staticmethod (foo)

With the addition of the ' @ ' decoration operator, you can do this:

@staticmethod

def foo (): Pass

This is why some people oppose decorators. Because ' @ ' is a bit of a grammatical sugar (syntax sugar, meaning the grammar that doesn't add new functionality to computer languages, but is more "sweet" to humans. Grammatical sugars often give programmers a more practical way of coding, which is useful for better coding styles and easier reading. But it doesn't add anything new to the language. (translator): Pass a Function object through another function, and then assign the result to the original function.

I think the reason why decorator has such a big impact is that it changes the way people think about programming with a little bit of grammatical sugar. In fact, it is formalized as a language concept, which makes the idea of "applying code to other code" (such as macros) in mainstream thinking.

more Useful

Now, let's go back to the first example. Here we implement something more conventional and actually use the code in the decorated function:

class Entryexit (object):

 

def __init__ (self, f):

self.f = f

 

def __call__ (self):

print "Entering", self.f.__name__

self.f ()

print "exited", self.f.__name__

 

@entryExit

def func1 ():

print "Inside Func1 ()"

 

@entryExit

def func2 ():

print "Inside Func2 ()"

 

func1 ()

Func2 ()

The output is:

entering Func1

inside Func1 ()

exited func1

entering Func2

inside Func2 ()

exited Func2

You can now see that the decorated function has "entering" and "exited" trace statements throughout the call.

The constructor holds the argument, which is the function object. In the call, we use the __name__ property of the function to display the function name, and then call the function itself.

using functions as decorators

For a decorator result, the only constraint is that it must be callable. This allows it to completely replace the decorated function. In the example above, I substituted the original function with an object of the class containing a __call__ () method. However, the function object is still callable. So we can rewrite the previous example by using a function (not a class), namely:

def entryexit (f):

def new_f ():

print "Entering", f.__name__

f ()

print "exited", f.__name__

return New_f

 

@entryExit

def func1 ():

print "Inside Func1 ()"

 

@entryExit

def func2 ():

print "Inside Func2 ()"

 

func1 ()

Func2 ()

Print func1.__name__

New_f () is defined in Entryexit (), so it is created and returned when the Entryexit () is invoked. Note that New_f () is a closure (closure) because it obtains the actual value of F.

As long as the New_f () is defined, it is returned from Entryexit () so that the decorator mechanism can assign the result as a decorated function.

The output of the ' Print func1.__name__ ' line is new_f because the New_f function has replaced the original function during decoration. If you have questions, you can change the name of the decorator function before the function returns:

def entryexit (f):

def new_f ():

print "Entering", f.__name__

f ()

print "exited", f.__name__

new_f.__name__ = f.__name__

return New_f

Dynamic access to information about functions, the ability to modify functions, is the strength of Python.

more examples

Now that you have a certain basis, you can see more examples of decorators here. Note the number of examples using classes as decorators

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.