Python Decorator Introduction

Source: Internet
Author: User
Tags python decorator
The adorner in Python is a gateway to the Python door, and it's there no matter how you cross it. The concept of adorners in Python often makes people confused, so take a look at the adorners in Python today.

1. Scope

In Python, scopes fall into two categories: global scope and local scope.

A global scope is a variable, a function name, that is defined at the file level. The local scope is defined inside the function.

About scopes, I want to understand two points: a. Variable b that is not globally accessible to a local definition. Globally defined variables can be accessed locally, but not globally defined variables (there are ways to modify them, of course)

Let's take a look at the following example:


x = 1def Funx ():  x = ten print  (x) # Print out 10funx () print (x) # prints out 1

If the variable x is not defined locally, the inside of the function will start looking for x from inside Out, and if not found, it will be an error.


x = 1def funx (): Print  (x) # prints out 1funx () print (x) # prints out 1x = 1def funx ():  def func1 (): Print    (x) # prints out 1  func1 () Funx () print (x) # prints out 1

Therefore, about the scope of the problem, only need to remember two points on the line: The global variable can be referenced anywhere in the file, but the modification can only be done globally; if the required variable is not found locally, it will be looked up and the error will be found without finding it.

2. Advanced functions

We know that the function name is actually the address that points to a memory space, since it is the address, then we can use this feature.

A function name can be used as a value


def Delete (PS): import os filename = ps[-1] Delelemetns = ps[1] with open (filename, encoding= ' utf-8 ') as f_read,\ O        Pen (' Tmp.txt ', ' W ', encoding= ' Utf-8 ') as f_write:for lines in ITER (F_read.readline, "): if line! = ' \ n ': # Handling non-empty rows If delelemetns in line:line = Line.replace (Delelemetns, ") F_write.write (line) os.remove (filename ) os.rename (' tmp.txt ', filename) def add (PS): filename = ps[-1] Addelemetns = ps[1] with open (filename, ' a ', encoding= ' u Tf-8 ') as Fp:fp.write ("\ n", Addelemetns) def modify (PS): import os filename = ps[-1] Modify_elemetns = ps[1] with O Pen (filename, encoding= ' utf-8 ') as F_read, \ Open (' Tmp.txt ', ' W ', encoding= ' Utf-8 ') as F_write:for line in ITER (f _read.readline, '): if line! = ' \ n ': # handles non-empty rows if modify_elemetns in Line:line = Line.replace (modify_ Elemetns, ') F_write.write (line) os.remove (filename) os.rename (' tmp.txt ', filename) def search (cmd): filename = Cmd[-1] Pattern = cmd[1] with open (filename, ' R ', encoding= "Utf-8") as F:for line in f:if pattern in Line:print (line, end= "") Else:print ("not Found") dic_func ={' delete ': Delete, ' Add ': Add, ' Modify ': Modify, ' Search ': search}while TRUE:INP = Input ("Please enter the action you want to take:"). Strip () if not inp:continue cmd_1 = inp.split () cmd = cmd_1[0] If cmd in Dic_func:dic_fun C[cmd] (cmd_1) else:print ("Error")

B. Function names can be used as return values


def outer ():  def inner ():    pass  return inners = outer () print (s) ##### #输出结果为 #######<function outer.< Locals>.inner at 0x000000d22d8ab8c8>

C.. Function name can be used as a parameter


def index ():  print ("index func") def outer (index):  s = index  s ()  outer (index) ##### #输出结果 ######### Index Func

So satisfying one of the above two conditions can be called advanced functions.

3. Closure function

The closure function must meet two conditions: 1. Functions defined inside the function 2. Contains references to external scopes rather than global scopes

Here are some examples to illustrate the closure function:

Example one: The following defines only one function within the function, but not the closure function.


def outer ():  def inner ():    print ("inner func excuted")  inner () # Call execute inner () function  print ("outer func excuted ") outer () # Call execution outer function # # # #输出结果为 ######### #inner func excutedouter func excuted

Example two: The following defines a function inside a function, and also refers to an external variable x, so is this a closure function? Answer: No.


x = 1def outer ():  def inner ():    print ("x=%s"%x) # references a variable print inside a non-inner function (    "inner func excuted")  inner ( # Execute inner function  print ("outer func excuted") outer () # # # # # # # # # # # #输出结果 ####### #x =1inner func excutedouter func excuted

Looking back at the definition of the closure function, is not two satisfied? Smart you, must find not satisfied with the second. Yes, the variable x here is a global variable, not an externally scoped variable. Then take a look at the following example:


def outer ():  x = 1  def inner ():    print ("x=%s"%x)    print ("inner func excuted")  inner ()  Print ("outer func excuted") outer () # # # # # # # # #输出结果 ######## #x =1inner func excutedouter func excuted

Obviously, the above instance satisfies the conditions of the closure function. Now, you should be aware that as a closure function, you have to meet the above two conditions, indispensable. However, in general, we will return a value to the closure function. Let's not say why. In the next section, you will see the purpose of this return value.


def outer ():  x = 1  def inner ():    print ("x=%s"%x) print ("    inner func excuted")  print ("outer func Excuted ") return  inner # returns the internal function name  outer ()

Now let's abstract the definition of the closure function. It is a combination of a function and its associated reference environment. When implementing a deep constraint, you need to create something that explicitly represents the reference environment and bundle it with the associated subroutine so that the bundle becomes a closure. In the above example, we can find that the closure function, which must contain its own function and an external variable, can really be called a closure function. If there is no external variable bound to it, then this function cannot be considered a closure function.

So how do you know how many external reference variables a closure function has? Take a look at the code below.


def outer ():  x = 1  y = 2  def inner (): Print (    "x=%s"%x)    print ("y=%s"%y)  print (inner.__ closure__)  return Innerouter () ##### #输出结果 ####### (<cell at 0x000000df9ea965b8:int object at 0x000000006fc2b440 <cell at 0x000000df9ea965e8:int object at 0x000000006fc2b460>)

The results show that within inner, two external local variables are referenced. If the reference is a non-local variable, the output here is none.

Features of the closure function:

1. With scope 2. Deferred calculation

So what does the closure function do? We know clearly that when a closure function is defined, it must be bound to an external environment. This whole can be counted as a closure function, then we can use this binding feature to accomplish some special functions.

Example three: According to the incoming URL, to download the page source code


From urllib.request import urlopendef index (URL)  def get ()    return Urlopen (URL). Read ()  return Getpython = Index ("http://www.python.org") # Returns the address of the Get function print (Python ()) # Executes the Get function and prints the returned results in Baidu = Index ("http:// Www.baidu.com ") Print (Baidu ())

One can say that this does not satisfy the condition of the closure function Ah! I don't have a reference to a non-global external variable. Not really, given, as we said before, as long as the variables inside the function belong to the function. So I'm at index (URL), this URL is also within the function, but we omit one step, so the above function is also a closure function.

4. Decorative Device

With the above basis, the adorner is well understood.

Adorner: The external function passes in the decorated function name, and the inner function returns the name of the decorated function.

Features: 1. Do not modify the calling method of the decorated function 2. The source code of the decorated function is not modified

A. Non-parametric adorner

With the following example, we need to calculate the time the code executes.


Import time, Randomdef index ():  time.sleep (Random.randrange (1, 5))  print ("Welcome to Index page")

According to the characteristics of the adorner, we cannot make any changes to index (), and the calling method cannot be changed. At this point, we can use the adorner to complete the function as above.


Import time, Randomdef outer (func): # passes the address of index to Func  def inner ():    start_time = Time.time ()    func ()  # Fun = Index that func holds the address of the external index function    end_time = time.time ()    print ("Run time%s"% (end_time-start_time))  return Inner # Returns the address of Inner Def Index ():  time.sleep (Random.randrange (1, 5))  print ("Welcome to Index page") Index = outer ( Index) # This returns the address of inner and re-assigns it to Indexindex ()

However, in some cases, the decorated function needs to pass parameters in, some functions do not need parameters, then how to deal with this variable parameter function? Let's take a look at the use of parametric adorners.

B. With a reference decorator


def outer (func): # passes the address of index to Func  def inner (*args, **kwargs):    start_time = Time.time ()    func (*args, * * Kwargs)  # fun = Index that func holds the address of the external index function    end_time = time.time ()    print ("Run time%s"% (End_time-start_time)) Return  Inner # Returns the address of the inner

Here are some examples of other cases.

If the decorated function has a return value


def Timmer (func):  def wrapper (*args,**kwargs):    start_time = Time.time ()    Res=func (*args,**kwargs) # Res to receive the return value of the home function    stop_time=time.time ()    print (' Run time is%s '% (stop_time-start_time))    return res   return Wrapperdef Home (name):  time.sleep (Random.randrange (1,3))  print (' Welecome to%s home page '% Name)  return 123123123123123123123123123123123123123123

To add, add that we are going to execute the decorated function, then it should be called the following way:

Home = Timmer (Home) # The right side of the equation returns the memory address of the wrapper and assigns it to home, where the home is not the original function, but the function that has been decorated. Like home = Timmer (home), Python gives us a convenient way to------grammar sugar @. In the future we have to write the @timmer before the decorated function, which is the same as Home = Timmer (home).

If a function is decorated by multiple adorners, what is the order of execution?


Import Timeimport randomdef Timmer (func):  def wrapper ():    start_time = Time.time ()    func ()    stop_time= Time.time ()    print (' Run time is%s '% (stop_time-start_time))  return wrapperdef auth (func):  def deco ():    name=input (' name: ')    password=input (' Password: ')    if name = = ' Egon ' and password = = ' 123 ':      print (' Login successful ')      func () #wrapper ()    else:      print (' Login err ')  return deco@auth  # index = Auth (Timmer (index))         @timmer # index = Timmer (index) def index ():   time.sleep (3)  print (' Welecome to index Page ') index ()

Experimental results show that multiple adorners decorate a function, whose execution order is from bottom to top.

About adorners, there are some high-level uses, interested in the research can be self-study.

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.