48

Say I have a list

data = []
data.append("A")
data.append("B")
data.append("C")
data.append("D")

How do I convert this to a generator? Any help with sample code would be highly appreciated...

Found a URL: http://eli.thegreenplace.net/2012/04/05/implementing-a-generatoryield-in-a-python-c-extension/

Is this what I want to do?

Neuron
  • 5,141
  • 5
  • 38
  • 59
swordholder
  • 4,519
  • 3
  • 18
  • 14

8 Answers8

70

Are you sure, you want to create a generator? A generator is function which returns an iterator type, constructed e.g. by using the yield keyword (cf. term-generator). If you really want this, steven-rumbalski's answer is precisely what you are looking for:

data_gen = (y for y in data)

Most of the time, you will want to directly create an iterator object, e.g. to use the next() method. In this case, the answer is implicit in the comment by mgilson above:

data_iter = iter(data)

which is equivalent to data_iter = data.__iter__(), cf. functions#iter.

Community
  • 1
  • 1
Heinrich Hartmann
  • 1,205
  • 11
  • 13
44
>>> (n for n in [1, 2, 3, 5])
<generator object <genexpr> at 0x02A52940>

works in Python 2.7.4+

>>> a2g = lambda x : (n for n in x)
>>> a2g([1, 2, 3, 4, 5])
<generator object <genexpr> at 0x02A57CD8>

Edit:

One more slight variation of a lambda generator factory pattern

>>> a2g = lambda *args: (n for n in args)
>>> for i in a2g(1, 2, 3, 4, 5): print i

1
2
3
4
5
David
  • 17,673
  • 10
  • 68
  • 97
7

The literal equivalent would be:

def data_generator():
    yield 'A'
    yield 'B'
    yield 'C'
    yield 'D'

Calling the generator function returns a generator-iterator. Passing the generator-iterator to the list constructor gives:

>>> list(data_generator())
['A', 'B', 'C', 'D']

This generator-iterator can also be created using a generator expression:

data_iter = (c for c in 'ABCD')

Note: You filled your list with four append statements. That's typically not how you would write it.

Rather do:

data = ['A', 'B', 'C', 'D']
Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
5
import itertools
iter_data = itertools.chain(data)

like so:

In [10]: data
Out[10]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [11]: iter_data=itertools.chain(data)

In [12]: iter_data
Out[12]: <itertools.chain at 0x1ce8950>

In [13]: iter_data.next()
Out[13]: 1
Cameron Sparr
  • 3,925
  • 2
  • 22
  • 31
2

You could use a generator function:

def gen():
    for x in "ABCD":
        yield x

In [9]: it = gen()

In [10]: next(it)
Out[10]: 'A'

In [11]: next(it)
Out[11]: 'B'

In [12]: next(it)
Out[12]: 'C'

In [13]: next(it)
Out[13]: 'D'
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1
>>> d = ['A', 'B', 'C', 'D']
>>> 
>>> def gen(d):
...     for i in d:
...             yield i
... 
>>> for i in gen(d):
...     print i
... 
A
B
C
D
>>> 
Yarkee
  • 9,086
  • 5
  • 28
  • 29
  • Is it possible to change this to a closure? Put your def inside a function that has the list at the same level as the def then return the generator with list included? – Mark Kortink Nov 04 '19 at 20:48
  • @MarkKortink You can: `gen = lambda d: (i for i in d)`. On the other hand, this is super unreadable and I would advice against using it anywhere in productive code. – Kaligule Apr 14 '22 at 05:02
1
(item for item in listNameHere).next()

This is the general way of doing it, if I recall correctly.

>>> a = [0,1,2,3,4]
>>> x = (item for item in a)
>>> x
<generator object <genexpr> at 0x028B8440>
>>> x.next()
0
>>> x.next()
1
>>> x.next()
2

etc etc.

Micaele
  • 11
  • 1
0

https://stackoverflow.com/a/21622696/2936673

In 3.x, there is no longer a .next method attached to these; instead, use the built-in free function next:

So to make and step through generator or iterator:

> list_iterator = (d for d in data)  # or list_iterator = iter(data)
> next(list_iterator)
'A'
Denis
  • 940
  • 12
  • 16