In [ ]:
from random import randrange
def randomly_generate_random_nonmultiples_of_ten_between_0_and_99():
while True:
digit = randrange(0, 100)
if digit % 10:
yield digit
else:
return
generator = randomly_generate_random_nonmultiples_of_ten_between_0_and_99()
while True:
try:
# Alternative: print(generator.__next__())
print(next(generator))
except StopIteration:
print('A multiple of 10 was generated, which ended the process')
break
In [ ]:
def generate_multiples_of(n):
for i in range(1, 10):
yield n * i
def generate_multiples():
for n in range(1, 10):
yield from generate_multiples_of(n)
count = 0
generator = generate_multiples()
for e in generator:
print('{:3d}'.format(e), end = '')
count += 1
if count % 9 == 0:
print()
In [ ]:
from random import randint
def randomly_announce_even_or_odd():
while True:
if randint(0, 1):
print('It is odd.')
else:
print('It is even.')
yield
generator = randomly_announce_even_or_odd()
for i in range(10):
next(generator)
In [ ]:
def yield_and_send():
sent = None
i = 0
while True:
if sent is None:
# "i" is generated.
# - If a call to "__next__()" follows,
# "sent" then receives the value None
# and this statement will be executed again after i has been incremented.
# - If a call to "send()" follows,
# "sent" then receives the value passed as an argument to "send()"
# and the body of the "elif" or "else" parts will be executed
# after i has been incremented.
sent = yield i
elif sent == 'stop':
return
else:
# Same as above, except that it is "sent + i" that is generated.
sent = yield sent + i
i += 1
generator = yield_and_send()
# First "next()" has to be issued, "send()" cannot be issued.
print(next(generator))
# Now either "next()" or "send()" can be issued:
# "yield i" has last been executed;
# which of "__next__()" or "send()" will be called
# will determine the value that "sent" will receive.
print(next(generator))
print(next(generator))
print(generator.send(10))
print(generator.send(20))
print(next(generator))
print(generator.send(30))
print(next(generator))
print(next(generator))
try:
print(generator.send('stop'))
except StopIteration:
print('Generation has been stopped')
In [ ]:
# More generally, any iterable.
L = [0, 3, 2, 5, 1]
# List comprehension
print([i * i for i in L])
print([i * i for i in L if i % 2])
print()
# Set comprehension
print({i * i for i in L})
print({i * i for i in L if i % 2})
print()
# Dictionnary comprehension
print({i: i * i for i in L})
print({i: i * i for i in L if i % 2})
print()
# "print((i: i * i for i in L))" and "print((i: i * i for i in L if i % 2)" are invalid:
# there is no tuple comprehension.
# "(i: i * i for i in L)" and "(i: i * i for i in L if i % 2)" are generator expressions:
# the call to "tuple()" in "tuple((i: i * i for i in L))",
# the call to "tuple()" in "tuple((i: i * i for i in L if i % 2))"
# force the generator to produce all values;
# the inner parentheses (for "generator expression") can be omitted.
print(tuple(i * i for i in L))
print(tuple(i * i for i in L if i % 2))
print()
for e in (i * i for i in L):
print(e, end = ' ')
print()
for e in (i * i for i in L if i % 2):
print(e, end = ' ')
print('\n')
# List, set and dictionnary comprehension can be achieved with a similar technique:
print(list(i * i for i in L))
print(list(i * i for i in L if i % 2))
print(set(i * i for i in L))
print(set(i * i for i in L if i % 2))
print(dict((i, i * i) for i in L))
print(dict((i, i * i) for i in L if i % 2))
print()
# The parentheses for "generator expression" can be omitted here too:
print(sorted(i * i for i in L))
# But they cannot be omitted here:
print(sorted((i * i for i in L), reverse = True))
In [ ]:
M = [[[111, 112, 113],
[121, 122, 123],
[131, 132, 133]],
[[211, 212, 213],
[221, 222, 223],
[231, 232, 233]]]
print([ 2 * element
for three_rows in M
for row in three_rows
for element in row])
print([ [ [ 2 * element
for element in row]
for row in three_rows]
for three_rows in M])
print()
print([ 2 * element
for three_rows in M
if three_rows[0][0] // 100 % 2
for row in three_rows
if row[0] // 10 % 2
for element in row
if element % 2])
print([ [ [ 2 * element
for element in row
if element % 2]
for row in three_rows
if row[0] // 10 % 2]
for three_rows in M
if three_rows[0][0] // 100 % 2])
In [ ]:
# More generally, any iterable.
R = range(5)
iterator_1 = iter(R)
print(iterator_1 is R)
print(next(iterator_1))
print(next(iterator_1))
iterator_2 = iter(R)
print(iterator_2 is iterator_1)
print(next(iterator_2))
print(next(iterator_1))
print(next(iterator_2))
print()
generator_expression = (e for e in R)
iterator_1 = iter(generator_expression)
print(iterator_1 is generator_expression)
print(next(iterator_1))
print(next(iterator_1))
iterator_2 = iter(generator_expression)
print(iterator_2 is iterator_1)
print(next(iterator_2))
print(next(iterator_1))
print(next(iterator_2))
print()
def generate_R_members():
for e in R:
yield e
generator = generate_R_members()
iterator_1 = iter(generator)
print(iterator_1 is generator)
print(next(iterator_1))
print(next(iterator_1))
iterator_2 = iter(generator)
print(iterator_2 is iterator_1)
print(next(iterator_2))
print(next(iterator_1))
print(next(iterator_2))