Python design pattern iterator and builder details (v)

Source: Internet
Author: User
Tags generator iterable

Iterators are a pattern of behavior in design patterns that provide a way to sequentially access individual elements in an aggregated object without exposing the object's internal representation. Python advocates the use of generators, which are also one of the iterators.

Series Articles
    • A single-instance pattern of Python design patterns (i)

    • Summary of common creation patterns of Python design patterns (ii.)

    • Python design pattern Decorator details (iii)

    • Python design mode with built-in adorner (iv)

    • Python design pattern iterator and builder details (v)

Python iterative object and iterator essentials:
    • Iterations are traversed, so an iterative object, by definition, is a data type or structure that can be traversed, and in Python it is the object that supports the for loop traversal.

    • Python has a iterable class that represents an iterative object, and all of the iterator objects belong to this class; The iterator class represents an iterator, and all iterator objects belong to this class;

    • What are the iterations of an object that can iterate? Because iterators are implemented internally by iterative objects, their performance in Python is the __iter__ magic method. This means that all python-built data structures such as STR, list, etc. have been implemented using the __ITER__ method in the definition structure.

The principles of an iterative object and an iterator

Based on the above points, we can customize the iterative objects:

from collections import Iterableclass MyIterable(object):    def __iter__(self):        passmy_iter = MyIteradle()print(isinstance(my_iter,Iterable))# 结果:True

Describes the Python interpreter by determining whether an object has a __iter__ magic method to determine if it is an iterative object. Now we try to use for...in ... Iterate through the iterative objects we define:

my_iter = MyIter()for i in my_iter:    print(i)结果:TypeError: iter() returned non-iterator of type 'NoneType'

The error, why? We need to know for...in ... What did you do:

When the Python interpreter encounters the for...in keyword, the first step is to find the My_iter object in the back, looking for the internal __iter__ magic method, which, if any, executes this method, which generates an iterator;

The second step takes a value out of the iterator and assigns the value to I.

So clearly, we have the __iter__ magic method above, but it does not return an iterator, nor does it take a value from the iterator. Then we need to implement an iterator.

To make it easier to understand, we think of an iterative object as a container in which our data is stored, an iterator that is imagined to be a prototype of an iterative object, a method that can sequentially access each element of an iterative object, and a for loop to get the iterator and fetch the data from the iterator.

Remember: an iterative object and its iterator are two different objects.

So we know that since the prototype of the iterator is an iterative object, then naturally there must be a __iter__ magic method, but this method requires that an iterator be returned, then not infinite loop? We can let it go back to it on its own. In addition, a method is implemented to fetch data from an iterator, and the Python interpreter specifies that the method is _next_.

from collections import Iterable, Iteratorclass MyIterator(object):    def __iter__(self):        return self    def __next__(self):        return 0my_iterator = MyIterator()print(isinstance(my_iterator, Iterator))for i in my_iterator:    print(i)# 结果:True

Without an error, we know that the object that implements the __iter__ and __next__ methods in Python is the iterator.

Are you done? No, look at the iterator definition: Provides a way to sequentially access individual elements in an aggregated object;

class MyIterator(object):    def __init__(self, mylist):        self.mylist = mylist        # current用来记录当前访问到的位置        self.current = 0    def __next__(self):        if self.current < len(self.mylist):            item = self.mylist[self.current]            self.current += 1            return item        else:            raise StopIteration    def __iter__(self):        return self
Explicit acquisition and use of iterators

Use for...in ... keyword, the Python interpreter automatically completes the process of getting iterators and fetching values from iterators, what if I want to manually step through this process? Python provides a dominant approach to ITER () and next ().

# 两种方法可以获取一个对象的迭代器l = [0,1,2]print(l.__iter__())print(iter(l))# 结果:<list_iterator object at 0x000002567EA5C518><list_iterator object at 0x000002567EA5C518>
    • Manual traversal
# 使用next方法取值l = [0,1,2]ter = iter(l)print(ter)while True:    try:        print(next(ter))    except StopIteration:        break
Generator

Generator is a special kind of iterator, what does it mean? If we want to customize an iterator, then we need to implement the __iter__ and __next__ methods manually, which is obviously too cumbersome, so Python gives us a quick and easy way.

def my_iterator(mylist):    current = 0    while current < len(mylist):        res = mylist[current]        current += 1        yield res    return '遍历完成'l = [0,1,2,3]F = my_iterator(l)for i in F:    print(i)

As you can see, we take the logic out of the __next__ method and use yield to return a result, and this simple structure is the generator, which is essentially a quick way to get an iterator.

At this point the return value of My_iterator is not acquired through the for loop, but requires stopiteration snapping.

l = [0,1,2,3]F = my_iterator(l)while True:    try:        next(F)    except StopIteration as e:        print("生成器返回值:%s"%e.value)        break

The next () function can wake the generator, and we can use the Send () method to wake the generator and pass a value to the generator at the same time.

def my_iterator(mylist):    current = 0    while current < len(mylist):        res = mylist[current]        current += 1        i = yield res        print(i)    return '遍历完成'l = [0,1,2,3]F = my_iterator(l)while True:    try:        f.send('aaaa')    except StopIteration as e:        print("生成器返回值:%s"%e.value)        break
Generator-generated

A quicker way to create a generator is when the logic is simple enough:

f = (i for i in range(10)) #   此时f表示的不是元组而是生成器
    • Tianyu tour
    • Source:/http www.cnblogs.com/cwp-bg/
    • This article is copyright to the author and the blog Park, welcome, exchange, but without the consent of the author must retain this statement, and in the article obvious location to give the original link.
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.