Key points of the decorator adorner pattern for analyzing design patterns in Python

Source: Internet
Author: User
Let's give a four-man Group A definition of decorator mode: Dynamically adding some extra responsibilities to an object.
Again, the benefits of this model: Authentication, permissions check, log, check parameters, lock, and so on, and so on, and so on, these functions and systems are not business-related, but it is necessary for the system, said more clearly, is the aspect-oriented programming (AOP).
In Python, decorator mode can be implemented in the same way as other programming languages such as C + +, Java, but Python's ability to apply decorative concepts goes far beyond this, and Python provides a syntax and a programming feature to enhance this functionality. The syntax provided by Python is the adorner syntax (decorator), as follows:

@aoodef foo (): Passdef Aoo (FN):  return fn

The decorative pattern emphasizes the dynamic addition of additional functionality to the object. Python has a lot of built-in support for adorners, so it's very easy to use decorating patterns in Python, and here's a typical example of adding log functionality to functions:

Import functoolsdef Log_wrapper: @functools. Wraps (Fun) def wrapper (*args, **kwargs):  print ' Add log before function execution '  ret = Fun (*args, **kwargs)  print ' After function execution home log '  return ret return wrapper@log_wrapperdef test (): print ' Hello, world '

Functools.wraps is a special adorner provided by the Python standard library to address some of the common problems that adorners bring, such as function name, Doc, and so on. @ is a syntax sugar provided by Python for adorners, the above @log_wrapper equivalent to Wrap_test = Log_rapper (test), after using @, this step is handled by the interpreter.

Adorners are a skill that must be mastered in Python programming and are often used during coding.

This is just a normal inline function.

def foo (x):  y = x  def foo1 ():    a = 1    return a  return foo1

And the following boo is a closed bag

Def Aoo (A, B):  C = a  def boo (x):    x = b + 1    return x  return Boo

Boo's particularity is that it refers to the external variable B, and when Aoo returns, the reference to B will persist as long as the return value (Boo) persists.
The above knowledge may take some time to digest, if you feel that you have mastered this knowledge, the following to get back to the topic, see how these language features to implement the concept of Python decoration.
Let's start by looking at a simple example and then step into it. This example is the lock, how to implement the lock function?
The specific requirements are this: I have an object that implements some functionality and provides some interfaces for other modules to call, which is running in a concurrent environment, so I need to synchronize the calls to the interface, the first version of the code is as follows:

Class Foo (object):  def __init__ (self, ...):    Self.lock = Threading. Lock ()  def interface1 (self, ...):    self.lock.acquire ()    try: Do     something    finally:     Self.lock.release ()  def interface2 (self, ...): Same as    Interface1 () ...  

The problem with this version of the code is obvious, that is, each interface function has the same locking/unlock code, Duplicate code brings more typing, more reading, more maintenance, and more changes, most of all, the programmer should have concentrated on the business of the energy is scattered, and please note that The real business code starts at 2 indents from the function definition, even if your display is widescreen, which can cause some reading difficulties.
You intuitively think that you can put this code into a function for reuse purposes, but notice that the code is not a complete block of code, but instead embeds the business code in the middle.
Now we use the decorator syntax to improve this part of the code to get the 2nd version of the code:

def sync (func): Def wrapper (*args, **kv): Self   = args[0]   self.lock.acquire ()   try:    return func (* args, **kv)   finally:    self.lock.release () return Wrapperclass Foo (object):  def __init__ (self, ...):    Self.lock = Threading. Lock ()  @sync  def interface1 (self, ...): do    something  @sync  def interface2 (self, ...):    do Something ...  

The first parameter of the

Adorner function is the function object to decorate, and the adorner function must return a function object. Like the sync function, when it decorates Interface1, the value of the parameter func is Interface1, the return value is wrapper, but the Interface1 of the class Foo instance is called, the wrapper function is actually called. The actual Interface1 is called indirectly in the body of the wrapper function, and when Interface2 is called, the wrapper function is also called, but since the Func has become interface2 at the time of decoration, Therefore, the actual Interface2 function is called indirectly.
Benefits of using adorner syntax:
The amount of code is greatly reduced, less code means less maintenance, less reading, less typing, benefits (reusable, maintainable)
users basically put most of their energy on the business code, and less lock code, Readability also increases the
Disadvantage:
Business Object Foo has a non-business data member lock, which is an eyesore;
a considerable degree of coupling, the first parameter of wrapper must be the object itself, and the decorated object must have a lock object present, This adds a limit to the client object and is not very comfortable to use.
We can think about it a step further:
Does the lock object have to be placed in Foo?
Typing @sync for each interface function, or annoying repetitive manual work, would still cause an inexplicable run-time error if a leak was added, why not concentrate?
in order to solve the above shortcomings, the 3rd version of the code is as follows:

Class Decorateclass (object): Def decorate (self):  for Name, FN in Self.iter ():   if not self.filter (name, FN):    Continue   self.operate (name, FN) class Lockerdecorator (Decorateclass): Def __init__ (self, obj, lock = threading. Rlock ()):  self.obj = obj  Self.lock = lock def iter (self):  return [(Name, GetAttr (self.obj, name)) for name in Dir (self.obj)] def filter (self, name, FN):  if not name.startswith ('_') and callable (FN):    return True  else:< C10/>return False def operate (self, name, FN):  def Locker (*args, **kv):   self.lock.acquire ()   try:    RETURN fn (*args, **KV)   finally:    self.lock.release ()  setattr (self.obj, Name, Locker) class Foo (object) :  def __init__ (self, ...):..    Lockerdecorator (self). Decorate ()  def interface1 (self, ...): Do    something  def interface2 (self, ...): Do    something  ...

The function of the object decoration is a more general function, not only for the interface lock, I use 2 classes to complete this function, Decorateclass is a base class, only defines the traversal and application of the decorative function of the algorithm code (template method), Lockerdecorator implements the ability to lock objects, where ITER is an iterator that defines how to traverse the members of the object (including data members and member functions), filter is the filters, defines what rules the member can become an interface, operate is the execution function, Specifically, the function of locking the object interface is implemented.
In the __init__ function of the Business class Foo, you only need to add one line of code at the end: Lockerdecorator (self). Decorate (), you can complete the function of locking the object.
If your object provides an interface that is specific, it can be implemented by simply overwriting the filter or inheriting the lockerdecorator and overriding the filter, and if you want to use other decorative functions, you can write a class that inherits from Decorateclass. and implement Iter,filter and operate three functions can be.

  • 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.