Python -> (11) Study Notes

Iterators, generators, decorator

  • Iterator
  • Builder
  • Generator expressions
  • Closure
  • Decorator

Iterator

Iteration is one of the most powerful features of Python is a way to access the collection elements. Iterator can remember the object is a traverse position.
Iterator object began a visit from the first element of the collection until all the elements are accessed session is over. Iterator can only move forward not backward.

Creating an iterator:

The use of a class as a need to implement two methods iterator (class has a constructor, Python constructor as class __init__(), object when it executes initialization.): __iter__(), Returns an iterator object itself .
__next__()Returns iterator next iteration object. If there is no next value can be returned, it should throw StopIterationan exception.

Example 1: Creating a digital iterator returns the initial value 1, gradually increasing 1:

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self
 
  def __next__(self):
    x = self.a
    self.a += 1
    return x
 
myclass = MyNumbers()
myiter = iter(myclass)
 
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))

Example 2:

class Counter(object):
    def __init__(self, low, high):
        self.current = low
        self.high = high

    def __iter__(self):
        return self

    def __next__(self):
        #返回下一个值直到当前值大于 high
        if self.current > self.high:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1
>>> c = Counter(5,10)
>>> for i in c:
...   print(i, end=' ')
...
5 6 7 8 9 10

Note: iterators can only be used once. Once thrown StopIteration, it will continue to throw the same exception:

>>> c = Counter(5,6)
>>> next(c)
5
>>> next(c)
6
>>> next(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in next
StopIteration
>>> next(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in next
StopIteration

Iterators in the loop for example:

>>> iterator = iter(c)
>>> while True:
...     try:
...         x = iterator.__next__()
...         print(x, end=' ')
...     except StopIteration as e:
...         break
...
5 6 7 8 9 10
Using an iterator:

Iterator There are two basic methods: iter()and next().
Strings, lists, tuples or objects can be used to create an iterator:

>>> list=[1,2,3,4]
>>> it = iter(list)    # 创建迭代器对象
>>> print (next(it))   # 输出迭代器的下一个元素
1
>>> print (next(it))
2

Iterator object can be used for conventional traverse statement:

#!/usr/bin/python3

list = [1,2,3,4]
it = iter(list)   # 创建迭代器对象
for x in it:
    print (x, end=" ")

You can also use next () function:

#!/usr/bin/python3
 
import sys         # 引入 sys 模块
 
list=[1,2,3,4]
it = iter(list)    # 创建迭代器对象
 
while True:
    try:
        print (next(it))
    except StopIteration:
        sys.exit()

Iterator

In Python, using the yieldfunctions are called generator (generator).
The difference is that with an ordinary function, the generator is a 返回迭代器function 只能用于迭代操作, easier to understand the point 生成器就是一个迭代器。
during a call to the generator running, each time experiencing yield function pauses and save all of the current operating information 返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行.
Calling a generator function, it returns an iterator object.
example 1:

>>> def my_generator():
...     print("Inside my generator")
...     yield 'a'
...     yield 'b'
...     yield 'c'
...
>>> my_generator()
<generator object my_generator at 0x7fbcfa0a6aa0>

In the example above, use the yield statement creates a simple generator, it can be used in a for loop, just like any other iterators as:

>>> for char in my_generator():
...     print(char)
...
Inside my generator
a
b
c

Example 2:

>>> def counter_generator(low, high):
...     while low <= high:
...        yield low
...        low += 1
... 
>>> for i in counter_generator(5,10):
...     print(i, end=' ')
... 
5 6 7 8 9 10

In the Whilecycle, each time to execute yieldwhen the statement, and returns the value of the variable low state to suspend generator. When the next call to the generator, the generator resumes variable low value and then increase from a place before freezing. Generator continues to whilecycle and once again came to yieldthe statement ...

Example 3:

#!/usr/bin/python3
 
import sys
 
def fibonacci(n): # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
 
while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()


# 输出:0 1 1 2 3 5 8 13 21 34 55

We usually use the generator for lazy evaluation. Such generator is a good way to use a large data processing. If you do not want to load all data in memory, you can use the generator, only one part of the data is passed to you.

os.path.walk()Function is the most typical example of this, it uses a callback function and the current os.walkgenerator. Using generators memory savings.

We can use the generator to generate an infinite number of values, such as:

>>> def infinite_generator(start=0):
...     while True:
...         yield start
...         start += 1
...
>>> for num in infinite_generator(4):
...     print(num, end=' ')
...     if num > 20:
...         break
...
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

A characteristic generator: they are not reusable.

Generator expressions

Generating a list of expressions is a high performance type and derivation of the generator, to promote higher memory efficiency.
For example, attempts to all numbers 1 to 9 is summing the squares:

>>> sum([x*x for x in range(1,10)])

This example is actually first created in memory a list of the value of a square, then walk through the list, after the release of the final summation memory. Can you understand memory usage is a big list of what.

Can be used to save memory generator expression :

>>> sum(x*x for x in range(1,10))

Grammar generator is always required to direct the expression in brackets in a pair, on both sides and can not comma. Expression Usage Example The following examples are valid Builder:

>>> sum(x*x for x in range(1,10))
285
>>> g = (x*x for x in range(1,10))
>>> g
<generator object <genexpr> at 0x7fc559516b90>

We can generator and generator expressions linked, in the following example we will read the file '/var/log/cron'and view any given task (we search for example 'anacron') run successfully.

We can use the shellcommand tail -f /etc/crontab |grep anacronto do the same thing (according to Ctrl + Cterminate the command execution).

>>> jobtext = 'anacron'
>>> all = (line for line in open('/etc/crontab', 'r') )
>>> job = ( line for line in all if line.find(jobtext) != -1)
>>> text = next(job)
>>> text
'25 6\t* * *\troot\ttest -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )\n'
>>> text = next(job)
>>> text 
'47 6\t* * 7\troot\ttest -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )\n'
>>> text = next(job)
>>> text
'52 6\t1 * *\troot\ttest -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )\n'

Closure

Closure (Closures) is a function returns a function by another . We use the closures to remove duplicate code. In the following example, we created a simple closure to the digital sum.

>>> def add_number(num):
...     def adder(number):
...         #adder 是一个闭包
...         return num + number
...     return adder
...
>>> a_10 = add_number(10)
>>> a_10(21)
31
>>> a_10(34)
44
>>> a_5 = add_number(5)
>>> a_5(3)
8

Decorator

Decorator (Decorators) some objects used to dynamically add some new behavior, we used the closures is the same.

Create a simple example, to print some statements before and after the function is executed:

>>> def my_decorator(func):
...     def wrapper(*args, **kwargs):
...         print("Before call")
...         result = func(*args, **kwargs)
...         print("After call")
...         return result
...     return wrapper
...
>>> @my_decorator
... def add(a, b):
...     #我们的求和函数
...     return a + b
...
>>> add(1, 3)
Before call
After call
4
Published 33 original articles · won praise 1 · views 1234

Guess you like

Origin blog.csdn.net/weixin_44783002/article/details/104747594