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