3 Ways to install a third-party library in Python

Source: Internet
Author: User
Tags function definition reflection wrapper in python

This article mainly introduces Python's adorner mode and aspect-oriented programming, in summary, the role of the adorner is to add additional functionality to the existing objects, this article details the various aspects of the adorner pattern, and then draws out the aspect-oriented programming knowledge, the need for friends can refer to the

Let's discuss the decorator today. The adorner is a very famous design pattern, often used in the section of the scene, the more classic has inserted log, performance testing, transaction processing and so on. Adorners are the perfect design for solving this type of problem, and with the adorner, we can pull out the same code that is irrelevant to the function itself in a large number of functions and continue to reuse it. In summary, the role of adorners is to add additional functionality to existing objects.

1. Introduction to Adorners

1.1. How is the demand coming?

The definition of adorners is very abstract, so let's look at a small example.

The code is as follows:

def foo ():

print ' in foo () '

Foo ()

This is a very boring function, yes. But suddenly there is a more boring person, we call him B-June, said I want to see how long it takes to perform this function, OK, so we can do this:

The code is as follows:

Import time

def foo ():

Start = Time.clock ()

print ' in foo () '

End = Time.clock ()

print ' used: ', End-start

Foo ()

Very good, the function looks unassailable. But the egg hurt B June suddenly do not want to see this function, he has another call Foo2 function produced a more intense interest.

What do we do? If you copy the above new code into the Foo2, this will make a big taboo ~ Copy what is not the most annoying it! and if B-June continues to look at other functions?

1.2. Status quo, is changed also

Remember, the function is a first-class citizen in Python, so we can consider redefining a function Timeit, passing the reference to Foo to him, then calling Foo in Timeit and timing, so that we achieve the purpose of not changing the Foo definition, and No matter how many functions B-June has seen, we don't have to modify the function definition!

The code is as follows:

Import time

def foo ():

print ' in foo () '

def Timeit (func):

Start = Time.clock ()

Func ()

End =time.clock ()

print ' used: ', End-start

Timeit (foo)

It doesn't seem to be a logical problem, everything is fine and working!...... Wait, we seem to have modified the code for the calling section. That's what we call it: Foo (), which is changed to: Timeit (foo). In this case, if Foo is called at N, you have to modify the code in the N place. Or, more extreme, consider the code in which a call is not able to modify the situation, such as: This function is for others to use.

1.3. Minimize changes to the minimum!

That being the case, we'll figure something out. Not modifying the calling code; If you do not modify the calling code, it means that calling Foo () requires the effect of calling Timeit (foo). We can think of assigning Timeit to Foo, but Timeit seems to have a parameter ... Find a way to unify the parameters! If Timeit (foo) returns a function that is consistent with the Foo argument list if it is not directly generating an invocation effect ... It's good to do, assign the return value of Timeit (foo) to Foo, and then the code to call Foo () is completely unmodified!

The code is as follows:

#-*-Coding:utf-8-*-

Import time

def foo ():

print ' in foo () '

# define a timer, pass in one, and return another method with the timer function attached

def Timeit (func):

# defines an inline wrapper function that adds the timer function to the incoming function.

def wrapper ():

Start = Time.clock ()

Func ()

End =time.clock ()

print ' used: ', End-start

# returns the Wrapped function back

Return wrapper

foo = Timeit (foo)

Foo ()

In this way, a simple timer is done! We only need to be able to achieve the timing by adding foo = Timeit (foo) before we can call Foo on the definition of Foo, which is the concept of the adorner, which looks like Foo was decorated with Timeit. In this example, a function needs to be timed when it enters and exits, which is called a cross section (Aspect), which is referred to as faceted-oriented programming (Aspect-oriented programming). In contrast to the traditional programming habits of top-down execution, it is like inserting a piece of logic horizontally into the process of executing a function. In a particular business area, you can reduce a lot of duplicate code. Aspect-oriented programming there are a lot of terminology, there is no more introduction, interested in the words can go to find relevant information.

This example is for demonstration purposes only and does not take into account the case of Foo with parameters and return values, the task of perfecting it is yours:

2. Python's additional support

2.1. Grammatical sugar

The above code seems to be no longer streamlined, and Python provides a syntactic sugar to reduce the amount of character input.

The code is as follows:

Import time

def Timeit (func):

def wrapper ():

Start = Time.clock ()

Func ()

End =time.clock ()

print ' used: ', End-start

Return wrapper

@timeit

def foo ():

print ' in foo () '

Foo ()

Focus on the @timeit of line 11th, adding this line to the definition is completely equivalent to writing foo = Timeit (foo), don't think that @ has another magic. In addition to the lack of character input, there is an additional benefit: this looks more like a decorative device.

2.2. Built-in Adorner

The built-in adorners have three, respectively, Staticmethod, Classmethod, and property, which are used to turn the instance methods defined in the class into static methods, class methods, and Class properties. Because functions can be defined in a module, the usefulness of static methods and class methods is not too much, unless you want full object-oriented programming. and attributes are not indispensable, Java has no attributes also live very moist. From my personal Python experience, I have not used the property, the use of Staticmethod and Classmethod frequency is very low.

The code is as follows:

Class Rabbit (object):

def __init__ (self, name):

Self._name = Name

@staticmethod

def newrabbit (name):

return Rabbit (name)

@classmethod

def newRabbit2 (CLS):

Return Rabbit (")

@property

def name (self):

Return Self._name

The property defined here is a read-only property, and you need to define a setter if you need to write:

The code is as follows:

@name. Setter

def name (self, name):

Self._name = Name

2.3. Functools Module

The Functools module provides two adorners. This module is added after Python 2.5 and is generally used more than this version. But my usual working environment is 2.4 t-t.

2.3.1. Wraps (wrapped[, assigned][, updated]):

This is a very useful adorner. Read the previous reflection of a friend should know that the function is a few special properties such as function name, after being decorated, the function name Foo in the example above will become the name of the wrapper function wrapper, if you want to use reflection, may cause unexpected results. This adorner solves this problem by retaining the special properties of the decorated function.

The code is as follows:

Import time

Import Functools

def Timeit (func):

@functools. Wraps (func)

def wrapper ():

Start = Time.clock ()

Func ()

End =time.clock ()

print ' used: ', End-start

Return wrapper

@timeit

def foo ():

print ' in foo () '

Foo ()

Print foo.__name__

First note the 5th line, if the annotation line, foo.__name__ will be ' wrapper '. Also believe that you have noticed that the adorner actually carries a parameter. In fact, he has two other optional arguments, the property names in the assigned are substituted by the assignment, and the property names in updated are merged using update, and you can get their default values by looking at the source code of Functools. For this adorner, the equivalent wrapper = Functools.wraps (func) (wrapper).

2.3.2. Total_ordering (CLS):

This adorner is useful for certain occasions, but it was added after Python 2.7. Its role is to implement a class with at least __lt__, __le__, __gt__, __ge__ one of the classes plus other comparison methods, which is a class adorner. If you find it difficult to understand, you may wish to take a closer look at this decorator's source code:

The code is as follows:

def total_ordering (CLS):

"" "Class decorator that fills in missing ordering methods" "

convert = {

' __lt__ ': [(' __gt__ ', lambda Self, other:other < self),

(' __le__ ', lambda Self, other:not other < self),

(' __ge__ ', lambda Self, other:not Self < Other)],

' __le__ ': [(' __ge__ ', lambda Self, other:other <= self),

(' __lt__ ', lambda Self, other:not other <= self),

(' __gt__ ', lambda Self, other:not self <= Other)],

' __gt__ ': [(' __lt__ ', lambda Self, other:other > Self),

(' __ge__ ', lambda Self, other:not other > Self),

(' __le__ ', lambda Self, other:not self > Other)],

' __ge__ ': [(' __le__ ', lambda Self, other:other >= self),

(' __gt__ ', lambda Self, other:not other >= self),

(' __lt__ ', lambda Self, other:not self >= Other)]

}

Roots = Set (dir (CLS)) & Set (convert)

If not roots:

Raise ValueError (' must define at least one ordering operation: < > <= >= ')

root = max (roots) # prefer __lt__ to __le__ to __gt__ to __ge__

For Opname, Opfunc in Convert[root]:

If Opname not in roots:

opfunc.__name__ = Opname

opfunc.__doc__ = getattr (int, opname). __doc__

SetAttr (CLS, Opname, Opfunc)

Return CLS

This article is all over here, if you have time, I'll tidy up an adorner used to check the parameter type. Put it up, sort of an application:)

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.