python 迭代器协议和生成器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 迭代器协议和生成器相关的知识,希望对你有一定的参考价值。

##############################
###  ITERATOR PROTOCOL AND GENERATORS ###
##############################

# Python uses the iterator protocol as a generic way to make objects iterable (allowing for the iteration through sequences).
# An iterator is any object that will yield objects to the Python interpreter when used in a contaxt like a for loop. Most methods
# that expect a list or list-like object will also accept any iterable object. 

# For instance, if you wirte for key in myDictionary, Python will attempt to create an iterator out of myDictionary
myDictionary = {1: 'cat', 2: 'a big snake', 3: 'rabbit'}

for key in myDictionary:
    print(key) # result is 1, 2, 3

# A generator is a concise way to construct a new iterable object. Whereas normal functions execute and return a single
# result at a time (erasing everything upon completion), generators return a sequence of mutiple results lazily, pausing 
# after each one call of the function. If you then call the function again, it'll serve up the next value in the sequence,
# remembering what what served up the last time the function was called (unlike a normal function with a return).
# To create a generator, use the yield keyword instead of return in a function. 
def my_gen():
    n = 1
    print('This is printed first')
    # Generator function contains yield statements
    yield n

    n += 1
    print('This is printed second')
    yield n

    n += 1
    print('This is printed at last')
    yield n

# you can iterator through the generator directly to get the entire sequence
for item in my_gen():
    print(item)  

'''
Result is:

This is printed first
1
This is printed second
2
This is printed at last
'''

# you can also assign the generator to a variable and use next() to get each value in the sequence individually
a = my_gen()
# when you assign to a variable, it won't execute any code yet. It doesn't execute code until you request on of the elements
a # <generator object my_gen at 0x0000021732E148E0>

# you can then use next to generate to request the element and therefore execute the code.
next(a)

'''
Result is the first yield statement:

This is printed first
1
'''

# using next again will get the next value in the sequence. Note that the previous call is still remembered, as you now get the second value.
next(a)

'''
Result is the second yield statement:

This is printed second
2
'''

# call it again and you'll get the third result
next(a)

'''
Result is:

This is printed at last
3
'''

# you're now out of yield keywords, so if you call it again you'll get a StopIteration error
next(a)

'''
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
'''

# another example of a generator function
def squares(n=10):
    print('Generating squares from 1 to {0}'.format(n ** 2))
    for i in range(1, n+1):
        yield i ** 2

# when you call the generator, no code is immediately executed:
generator = squares()
generator # result is <generator object squares at 0x0000021732E14780>

# it is not until you request elements from the generator that it begins executing its code:
for x in generator:
    print(x)

    # result is     Generating squares from 1 to 100
    #               1 4 9 16 25 36 49 64 81 100 

# you can also do this using a generator expression, which is a generate analogue to list, dict and set comprehensions. Generator 
# expressions can be used instead of list comprehensions as function arguments in many cases.
# To create one, enclose what would otherwise be a list comprehension within parentheses instead of brackets:
generator = (x ** 2 for x in range(100))
generator # result is <generator object <genexpr> at 0x0000021732E14888>


##############################
###  ITERTOOLS MODULE ###
##############################

# The standard library itertools module has a collection of generators for many common data algorithms. For example, grouby takes any 
# sequence and a function, grouping consecutive elements in the sequence by return value of the function.
import itertools
first_letter = lambda x: x[0]
names = ['Alan', 'Adam', 'Soren', 'Steven', 'Albert', 'Will']
for letter, names in itertools.groupby(names, first_letter):
    print(letter, list(names)) # names is a generator

    # Result is:

    # A ['Alan', 'Adam']
    # S ['Soren', 'Steven']
    # A ['Albert']
    # W ['Will']

以上是关于python 迭代器协议和生成器的主要内容,如果未能解决你的问题,请参考以下文章

python基础之迭代器协议和生成器

Python学习之路8?迭代器协议和生成器

Python学习——02-Python基础——5-迭代器协议和生成器

python学习------迭代器协议和生成器

第八篇 迭代器协议和生成器

Python基础-----迭代器协议和For循环机制