Iterable using yield or __next__()

Burton2000 :

I am looking at making iterable objects and am wondering which of these two options would be the more pythonic/better way, is there no difference or have I got wrong idea about using yield? To me using yield seems cleaner and apparently it is faster than using __next__() but i'm not sure.

class iterable_class():

    def __init__(self, n):
        self.i = 0
        self.n = n

    def __iter__(self):
        return self

    def __next__(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()

Using yield:

class iterable_class_with_generator():

    def __init__(self, n):
        self.i = 0
        self.n = n

    def __iter__(self):
        while self.i < self.n:
            yield self.i
            self.i += 1
user4815162342 :

One observable difference is that the first version implements an iterator (an object that has __next__ and whose __iter__ returns itself), while the second one implements an iterable (an object that can implements __iter__ to create some iterator). In most cases this doesn't make a difference because the for statement and all itertools accept any iterable.

The difference is visible with the following code:

>>> x = iterable_class(10)
>>> next(x)
0
>>> next(x)
1
>>> list(x)
[2, 3, 4, 5, 6, 7, 8, 9]

Obviously this won't work with iterable_class_with_generator because it doesn't implement __next__. But there is a deeper difference: since list(x) accepts any iterable, it would first call x.__iter__(), which would in case of iterable_class_with_generator create a new generator which would start the count from the beginning. A true generator-based iterator is presented at the end of the answer, but in most cases the difference won't matter.

Regarding the style difference of whether to use a generator or define your own __next__, both will be recognized as correct Python, so you should choose the one that reads better to the person or team who will maintain the code. Since the generator version is shorter and generators are a well-understood Python idiom, I'd choose that one.

Note that if you implement __iter__ with a generator, you don't need to keep iteration state in instance vars because the generator does it for you. The code is then even simpler:

class iterable_class_with_generator:
    def __init__(self, n):
        self.n = n

    def __iter__(self):
        for i in range(self.n):
            yield i


Finally, here is a version of iterable_class_with_generator that implements a true iterator that uses a generator internally:

class iterable_class_with_generator:
    def __init__(self, n):
        self._gen = self._generate(n)

    def __iter__(self):
        return self

    def __next__(self):
        return next(self._gen)

    def _generate(self, n):
        for i in range(n):
            yield i

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

TOP Ranking

  1. 1

    Failed to listen on localhost:8000 (reason: Cannot assign requested address)

  2. 2

    Loopback Error: connect ECONNREFUSED 127.0.0.1:3306 (MAMP)

  3. 3

    How to import an asset in swift using Bundle.main.path() in a react-native native module

  4. 4

    pump.io port in URL

  5. 5

    Compiler error CS0246 (type or namespace not found) on using Ninject in ASP.NET vNext

  6. 6

    BigQuery - concatenate ignoring NULL

  7. 7

    ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

  8. 8

    ggplotly no applicable method for 'plotly_build' applied to an object of class "NULL" if statements

  9. 9

    Spring Boot JPA PostgreSQL Web App - Internal Authentication Error

  10. 10

    How to remove the extra space from right in a webview?

  11. 11

    java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

  12. 12

    Jquery different data trapped from direct mousedown event and simulation via $(this).trigger('mousedown');

  13. 13

    flutter: dropdown item programmatically unselect problem

  14. 14

    How to use merge windows unallocated space into Ubuntu using GParted?

  15. 15

    Change dd-mm-yyyy date format of dataframe date column to yyyy-mm-dd

  16. 16

    Nuget add packages gives access denied errors

  17. 17

    Svchost high CPU from Microsoft.BingWeather app errors

  18. 18

    Can't pre-populate phone number and message body in SMS link on iPhones when SMS app is not running in the background

  19. 19

    12.04.3--- Dconf Editor won't show com>canonical>unity option

  20. 20

    Any way to remove trailing whitespace *FOR EDITED* lines in Eclipse [for Java]?

  21. 21

    maven-jaxb2-plugin cannot generate classes due to two declarations cause a collision in ObjectFactory class

HotTag

Archive