19

Is it acceptable/Pythonic to use a method in a class as a generator? All the examples I have found show the yield statement in a function, not in a class.

Here is an example working code:

class SomeClass(object):
    def first_ten(self):
        for i in range(10):
            yield i

    def test(self):
        for i in self.first_ten():
            print i

SomeClass().test()
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
jgrant
  • 1,273
  • 1
  • 14
  • 22
  • 1
    I would guess that most examples are functions because that's simpler; you don't need to be in a class, so it isn't shown. – jonrsharpe May 20 '16 at 14:35

1 Answers1

34

Yes, this is perfectly normal. For example, it is commonly used to implement an object.__iter__() method to make an object an iterable:

class SomeContainer(object):
    def __iter__(self):
        for elem in self._datastructure:
            if elem.visible:
                yield elem.value

However, don't feel limited by that common pattern; anything that requires iteration is a candidate for a generator method.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    +1 that iterator pattern is a good example. http://www.diveintopython3.net/ by Mark Pilgrim covers some of this. – Pax Vobiscum May 20 '16 at 14:47
  • If you are getting `TypeError: 'SomeContainer' object is not an iterator`, you are probably trying something like `sc = SomeContainer` with `next(sc)` to get each value. Instead do `sc_iter = iter(sc)` and then `next(sc_iter)`. See (https://www.oreilly.com/library/view/python-cookbook-3rd/9781449357337/ch04.html). – DocOc Sep 21 '19 at 12:17
  • 1
    You mean `sc = SomeContajner()`, probably :-) Yes, `SomeContainer()` instances are iterable, they are not an iterator object. `next()` requires an iterator, and `iter()` produces an iiterator from an iterable. The difference is that an iterable can produce any number of iterators, but iterators are single-use. – Martijn Pieters Sep 21 '19 at 13:01