Python's iterators and generators use instances
- 2020-04-02 14:29:22
- OfStack
One, Iterators
An iterator is simply a container object that implements the iterator protocol. It has two basic methods:
1) next method
Returns the next element of the container
2) s method
Returns the iterator itself
Iterators can be created using the built-in iter method, see examples:
>>> i = iter('abc')
>>> i.next()
'a'
>>> i.next()
'b'
>>> i.next()
'c'
>>> i.next()
Traceback (most recent call last):
File "<string>", line 1, in <string>
StopIteration:
class MyIterator(object):
def __init__(self, step):
self.step = step
def next(self):
"""Returns the next element."""
if self.step==0:
raise StopIteration
self.step-=1
return self.step
def __iter__(self):
"""Returns the iterator itself."""
return self
for el in MyIterator(4):
print el
--------------------
Results:
3
2
1
0
Two, generator power
Starting with Python2.2, generators provide a concise way to help return functions of list elements to complete simple and efficient code.
It is based on the yield directive, allowing the function to be stopped and the result to be returned immediately.
This function saves its execution context and can continue execution immediately if needed.
For example, the Fibonacci function:
def fibonacci():
a,b=0,1
while True:
yield b
a,b = b, a+b
fib=fibonacci()
print fib.next()
print fib.next()
print fib.next()
print [fib.next() for i in range(10)]
--------------------
Results:
1
1
2
[3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
PEP Python Enhancement Proposal Python Enhancement Proposal
Tokenize module
>>> import tokenize
>>> reader = open('c:/temp/py1.py').next
>>> tokens=tokenize.generate_tokens(reader)
>>> tokens.next()
(1, 'class', (1, 0), (1, 5), 'class MyIterator(object):/n')
>>> tokens.next()
(1, 'MyIterator', (1, 6), (1, 16), 'class MyIterator(object):/n')
>>> tokens.next()
(51, '(', (1, 16), (1, 17), 'class MyIterator(object):/n')
Example:
def power(values):
for value in values:
print 'powering %s' %value
yield value
def adder(values):
for value in values:
print 'adding to %s' %value
if value%2==0:
yield value+3
else:
yield value+2
elements = [1,4,7,9,12,19]
res = adder(power(elements))
print res.next()
print res.next()
--------------------
Results:
powering 1
adding to 1
3
powering 4
adding to 4
7
Keep the code simple, not the data.
Note: it is better to have a large number of simple iterable functions than a complex function that only computes one value at a time.
Example:
def psychologist():
print 'Please tell me your problems'
while True:
answer = (yield)
if answer is not None:
if answer.endswith('?'):
print ("Don't ask yourself too much questions")
elif 'good' in answer:
print "A that's good, go on"
elif 'bad' in answer:
print "Don't be so negative"
free = psychologist()
print free.next()
print free.send('I feel bad')
print free.send("Why I shouldn't ?")
print free.send("ok then i should find what is good for me")
--------------------
Results:
Please tell me your problems
None
Don't be so negative
None
Don't ask yourself too much questions
None
A that's good, go on
None