Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python generators; two apparently identical programs work differently

The program below [Python 3.4] is a simple Eratosthenes sieve:

from itertools import *
def excl(ns,pr):
    return (i for i in ns if i%pr)
def sieve(ns):
    while True:
        pr=next(ns)
        yield pr
        ns=excl(ns,pr)
        # ns=(i for i in ns if i%pr)
r=list(islice(sieve(count(2)),10))

which produces [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]. OK. Uncommenting the line which inlines excl(), and commenting the call, gives [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]. Why?

Is it related to troubles expected when modyfing a sequence inside a loop which iterates over it?

Thank you for any hint.

like image 616
Jerzy Karczmarczuk Avatar asked Oct 17 '15 20:10

Jerzy Karczmarczuk


People also ask

What is the advantage of using generators in Python?

Generators allow you to create iterators in a very pythonic manner. Iterators allow lazy evaluation, only generating the next element of an iterable object when requested. This is useful for very large data sets. Iterators and generators can only be iterated over once.

How does generators work in Python?

A Python generator is a function that produces a sequence of results. It works by maintaining its local state, so that the function can resume again exactly where it left off when called subsequent times. Thus, you can think of a generator as something like a powerful iterator.

Are generators lazy in Python?

Key takeaways: motivation and uses behind generators Generators are memory efficient since they only require memory for the one value they yield. Generators are lazy: they only yield values when explicitly asked. You can feed the output of a generator to the input of another generator to form data pipelines.

Are generators more efficient Python?

Generators help us with memory efficiency. They help with time efficiency. They act like iterators. So we don't need to implement our own iterators from scratch.


1 Answers

Your problem is that the pr referred to by the generator expression is the same pr that you modify in the next iteration of your while loop, so every number that is not divisible by the previous 'prime' number is treated as 'prime'. Which itself modifies pr and so in. In the excl function, the pr that you refer to is the one passed as an argument, which never changes.

like image 69
pppery Avatar answered Nov 03 '22 06:11

pppery