Step Python3 (four)--decorators, iterators, and generators

Source: Internet
Author: User

First knowledge decorator (decorator)

Python's decorator is essentially a high-order function that takes a function as an argument and then returns a new function.

Use decorator with the @ syntax provided by Python , so you can avoid manually writing F = decorate (f) code.

Let's look at an example:

#!/usr/bin/env pythondef Outer (func):    print (' This is outer. ')    def inner ():        print (' This is inner. ')        func ()        print (' This is the last. ')    return inner@outerdef F1 ():    print (' This is F1. ') F1 ()

Output Result:

This is outer.
This is inner.
This is F1.
This is the last.

Surprised by the output? The following is a detailed procedure of the execution of this code.

    • The code executes from top to bottom, loading the outer function and the F1 function into memory, and then calling F1 ()
    • A row plus @outer in front of the F1 function means that the outer adorner is called
    • When the F1 function is executed, F1 is passed into the adorner outer as a parameter and executed outer
    • Adorner outer parameter func is actually the function F1, and outer return value inner will be assigned to F1, so "Rerurn inner" This code is necessary, and the original F1 will be inner replaced
    • Execute the adorner outer first output “这是outer。” , the following in the execution function inner (inner is actually the new F1), output "This is inner." "And then execute the Func function, func实际上就是上一步传入的f1 so executing func () is executing the original function F1 (), so output" this is F1. ", and then output"这是最后。"

This implementation process needs to be understood by the parties.

If it is not possible to comprehend, it can be understood that the adorner is to give the function a decoration, so that the function can be done before or after execution or before and after the execution of some other things.

The following is a slight modification of the code to make it a function with parameters.

#!/usr/bin/env pythondef Outer (func):    print (' This is outer. ')    def inner (y):        print (' This is inner. ')        R = func (y)        print (' This is the last. ')        return R    return inner@outerdef F1 (x):    x + = +    print (' This is F1. ')    return XA = f1 (a) print (a) @outerdef F2 (x):    x-=-    print (' This is F2
#!/usr/bin/env pythondef Outer (func):    print (' This is outer. ')    def Inner (*args,**kwargs):        print (' This is inner. ')        R = func (*args,**kwargs)        print (' This is the last. ')        return R    return inner@outerdef F1 (x):    x + = +    print (' This is F1. ')    return XA = f1 (a) print (a) @outerdef F2 (x, Y, z):    a = x+y+z    print (' This is F2. ')    return AA = F2 (10,20,30) print (a)

The output is as follows:

This is outer.
This is inner.
This is F1.
This is the last.
110
This is outer.
This is inner.
This is F2.
This is the last.
60

。 ')    return XA = f2 (a)

Output Result:

This is outer.
This is inner.
This is F1.
This is the last.
110
This is outer.
This is inner.
This is F2.
This is the last.
-90

You can see that we have added parameters and return values to F1, so the corresponding inner in the adorner also needs to add parameters and return values.

And we have added the function F2, also can use only the adorner outer.

Sleep (100000000)

After careful understanding we proceed to the next step, if the function F2 with 2 or more parameters, but also with only one parameter F1 with the adorner outer?

Of course:

def outer (func):    print (' This is outer. ')    def Inner (*args,**kwargs):        print (' This is inner. ')        R = func (*args,**kwargs)        print (' This is the last. ')        return R    return inner@outerdef F1 (x):    x + = +    print (' This is F1. ')    return XA = f1 (a) print (a) @outerdef F2 (x, Y, z):    a = x+y+z    print (' This is F2. ')    return AA = F2 (10,20,30) print (a)

Output Result:

This is outer.
This is inner.
This is F1.
This is the last.
110
This is outer.
This is inner.
This is F2.
This is the last.
60

F1 and F2 are visible with different numbers of parameters, but the adorner outer can play a role. The key is the Universal parameter: "*args,**kwargs"

So can the same function have more than one adorner?

The answer is: no

Haha, can't be impossible. Please see:

#!/usr/bin/env pythondef Outer1 (func):    def Inner (*args,**kwargs):        print (' This is the inner of adorner 1. ')        R = func (*args,**kwargs)        print (' This is the end of adorner 1. ')        return R    return innerdef Outer2 (func):    def Inner (*args,**kwargs):        print (' This is the inner of adorner 2. ')        R = func (*args,**kwargs)        print (' This is the end of adorner 2. ')        return R    return inner@outer2@outer1def F1 (x):    x + = +    print (' This is F1. ')    return XA = f1 (a)

The output is as follows:

This is the inner of the adorner 2.
This is the inner of the adorner 1.
This is F1.
This is the end of the adorner 1.
This is the end of the adorner 2.
110

We reverse the order of the two adorners:

#!/usr/bin/env pythondef Outer1 (func):    def Inner (*args,**kwargs):        print (' This is the inner of adorner 1. ')        R = func (*args,**kwargs)        print (' This is the end of adorner 1. ')        return R    return innerdef Outer2 (func):    def Inner (*args,**kwargs):        print (' This is the inner of adorner 2. ')        R = func (*args,**kwargs)        print (' This is the end of adorner 2. ')        return R    return inner@outer1@outer2def F1 (x):    x + = +    print (' This is F1. ')    return XA = f1 (a)

The output is as follows:

This is the inner of the adorner 1.
This is the inner of the adorner 2.
This is F1.
This is the end of the adorner 2.
This is the end of the adorner 1.
110

Did you see that? Two adorners are the equivalent of a layer outside and a layer of decoration.

Conclusion: To want your code to look full, more than the whole point decoration ...

At last:

Is there anything more hanging from the decorator?

#!/usr/bin/env python# Version = 3.5.2__auth__ = ' Nameless Little Demon ' def fout (A1, A2):    def outer (main_func):        def wrapper ( Request, Kargs):            print (A1 ())            Main_result = Main_func (Request, Kargs)            print (A2 ())            return Main_result        return wrapper    return Outerdef F1 ():    a1 =    return A1def f2 ():    a2 =    return A2@fout (F1 , F2) def index (Request,kargs):    print (Request,kargs) index (20,30)

The output is as follows:

100
20 30
200

‘‘‘ 1、第一步:把def fout(a1,a2): 加载到内存 2、第二步:@fout(f1,f2)  ==》 调用了装饰器  ==》  return outer 然后返回给函数Index 3、第三步:执行outer函数并 Index ==》 wrapper 4、执行wrapper 函数,这样做的意义就是除了原函数给的参数外,装饰器也可以调用自己定义的参数 ‘‘‘ Initial knowledge iterator (iterator)

Iterators are a way to access the elements of a collection. An iterator object is accessed from the first element of the collection, knowing that all of the elements have been accessed and finished. Iterators can only move forward without going backwards, but that's fine, because people seldom retreat in the middle of an iteration.

Advantages of using iterators

For primitive data structures that support random access (such as tuple, list), there is no advantage over the index access of the iterator and the classic for loop, but the index value is lost (you can use the built-in function enumerate () to retrieve the index value). But for data structures that cannot be accessed randomly (such as set), iterators are the only way to access elements.

In addition, one of the great advantages of iterators is that they do not require that all elements in the entire iteration be prepared in advance. An iterator computes an element only when it iterates over it, and before or after that, the element may not exist or be destroyed. This feature makes it particularly useful for traversing large or infinite collections, such as several G files, or Fibonacci sequences, and so on.

The greater credit for iterators is the provision of an interface for a unified access collection, which can be accessed using iterators as long as the __iter__ () method object is defined.

There are two basic methods for iterators:

(1) __next__ returns the next item in the container

(2) __iter__ returns the iterator itself

The following is an example of how to generate Fibonacci numbers to illustrate why iterators

Code 1

Def FAB (max):     N, a, b = 0, 0, 1 while     n < max:         print B         A, B = B, a + b         n = n + 1

Printing with print directly in the function fab (max) causes the reusability of the function to be poor, because Fab returns none. Other functions cannot get the sequence returned by the FAB function.

Code 2

Def FAB (max):     L = []    n, a, b = 0, 0, 1 while     n < max:         l.append (b)         A, B = B, a + b         n = n + 1
   
    return L
   

Code 2 satisfies the need for reusability, but takes up memory space, preferably not.

Code 3

Contrast

For I in range (+): Pass
For I in Xrange (£): Pass

The previous one returns a list of 1000 elements, the second one returns an element in each iteration, so you can use iterators to solve the problem of reusable space

Class Fab (object):     def __init__ (self, max):         Self.max = Max         SELF.N, self.a, self.b = 0, 0, 1     def __iter_ _ (Self):         return self     def next:         if SELF.N < self.max:             r = self.b             self.a, self.b = self.b, SELF.A + self.b             SELF.N = SELF.N + 1             return R         raise Stopiteration ()

Perform

123456789 >>> for key in Fabs(5):    printkey     11235

The Fabs class continuously returns the next number of columns through next (), and memory consumption is always constant.

Also, as we mentioned earlier, using the built-in function iter () can get an iterator object:

>>> LST = range (5) >>> it = iter (LST) >>> It<range_iterator object at 0x001bc518>

The next element can be accessed using the __next__ () method:

>>> it.__next__ () 0>>> it.__next__ () 1>>> it.__next__ () 2

Use __ITER__ () to return the iterator itself:

>>> it.__iter__ () <range_iterator object at 0x001bc518>

First Knowledge Generator (Generator)

The function with yield is called the generator (generator) in Python, with several examples (or the generation of Fibonacci sequence descriptions) .

You can see that the code 3 is far from the code 1 concise, the generator (yield) can maintain the simplicity of code 1, but also maintain the effect of code 3.

Code 4

>>> def Fab (max): ...   N, a, b = 0, 0, 1 ...   While n < max: ...     Yield b     ... A, B = B, a + b     ... n = n + 1...>>> for n in Fab (5): ...   Print (n) ... 11235>>>

Simply put, the function of yield is to turn a function into a generator, the function with yield is no longer a normal function, the Python interpreter treats it as a generator, the call to Fab (5) does not execute the FAB function, but instead returns an it Erable Object ! When the For loop executes, each loop executes the code inside the FAB function, and when it executes to yield B, the FAB function returns an iteration value , and the next iteration, the code proceeds from the next statement of Yield B, and the local variable of the function looks and The last time the interrupt was executed is exactly the same, and the function continues until the yield is encountered again. It looks as if a function was interrupted several times by yield during normal execution, and each break returns the current iteration value through yield.

return effect

In a generator, if there is no return, the default execution is done to the function, and if a return is encountered, the stopiteration terminating iteration is thrown directly.

Code 5 File Read

def read_file (Fpath):     block_size = 1024x768     with open (Fpath, ' RB ') as F: While         True:             BLOCK = F.read (block_ SIZE)             if block:                 yield block             else:                 return

Calling the Read () method directly on a file object causes unpredictable memory consumption. A good approach is to use fixed-length buffers to continuously read the contents of the file. With yield, we no longer need to write an iterative class of read files, so we can easily implement file reads.

Step Python3 (four)--decorators, iterators, and generators

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.