Generator
Iterable Objects
#!/usr/bin/python
#list
l = range(10);
for i in l:
print (i)
#tuple
t = (1, 2, 3, 4);
for i in t:
print (i)
#dict
d = {'x':1, 'y':2};
for k in d:
print (k, d[k])
#string
s = 'Hello World!';
for i in s:
print (i)
Iterator
#!/usr/bin/python
l = iter(range(10)); #iterator
try:
while True:
print(next(l)) #if no more element, raise StopIteration
except StopIteration:
pass
Implement Iterator as Classes
#!/usr/bin/python
class yrange:
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self): # make an object iterable
#print('Call __iter__ ...')
self.i = 0
return self # return an iterator
def __next__(self):
#print('Call __next__ ...')
if self.i < self.n:
i = self.i
self.i += 1
return i
else:
raise StopIteration()
y = yrange(10);
l = list(y); # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(l)
l = list(y); # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(l)
- Iterable and iterator are same, it is consumed in a single iteration
#!/usr/bin/python
class zrange:
def __init__(self, n):
self.n = n
def __iter__(self):
return zrange_iter(self.n)
class zrange_iter:
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
# Iterators are iterables too.
# Adding this functions to make them so.
return self
def __next__(self):
if self.i < self.n:
i = self.i
self.i += 1
return i
else:
raise StopIteration()
l = zrange(10);
print(list(l)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(l)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
- Iterable and iterator are not same, every time a new iterator is created, is able to be re-used, same as xrange
Generator
#!/usr/bin/python
def yrange(n):
i = 0;
while i < n:
yield i;
i += 1
l = yrange(10);
for i in l:
print(i)
for i in l: # do not print anything, l has been consumed
print(i)
- Generator is iterator, can be consumed in a single iteration
Generator Expression
#!/usr/bin/python
# list
l = [x*x for x in range(4)]; # [0, 1, 4, 9]
print(l)
# generator
g = (x*x for x in range(4));
for i in g:
print(i)
for i in g: # do nothing, g has been consumed in the above for loop
print(i)
Reference