Path: csiph.com!usenet.pasdenom.info!gegeweb.org!usenet-fr.net!nerim.net!novso.com!newsfeed.xs4all.nl!newsfeed4.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.011 X-Spam-Evidence: '*H*': 0.98; '*S*': 0.00; 'none:': 0.07; 'referring': 0.07; 'immutable': 0.09; 'python': 0.11; 'def': 0.12; 'suggest': 0.14; 'itself.': 0.14; 'constructs': 0.16; 'iterable': 0.16; 'iterables': 0.16; 'iterated': 0.16; 'iterator': 0.16; 'iterators': 0.16; 'object).': 0.16; 'wrote:': 0.18; 'value.': 0.19; '(the': 0.22; 'feb': 0.22; 'otherwise,': 0.22; 'mon,': 0.24; 'source': 0.25; 'this:': 0.26; 'values': 0.27; 'header:In-Reply- To:1': 0.27; 'raise': 0.29; 'message-id:@mail.gmail.com': 0.30; "d'aprano": 0.31; 'steven': 0.31; 'trivial': 0.31; 'yourself.': 0.31; 'class': 0.32; '(e.g.': 0.33; 'skip:_ 10': 0.34; 'skip:s 30': 0.35; 'received:google.com': 0.35; 'there': 0.35; 'version': 0.36; 'next': 0.36; 'method': 0.36; 'should': 0.36; 'to:addr :python-list': 0.38; 'pm,': 0.38; 'track': 0.38; 'itself': 0.39; 'to:addr:python.org': 0.39; 'even': 0.60; 'new': 0.61; 'range': 0.61; 'simply': 0.61; 'more': 0.64; 'determine': 0.67; '2015': 0.84; 'self.value': 0.84; 'subject:skip:S 10': 0.84 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; bh=TDdmKjgJxvnS6CXv0871YZaob4UZIKGITpFN5gluAiY=; b=DzWiYUv2Ya4yEgxKXUoduE+5GLBsTcaaFlJsFWzkN8ag91FprOnBuyrTWsEBJhRY/z lOJqLpbmj118kzNSaw57BpDe1x1MuYYY0BXm1uNDUGZoHmfx50VBL0cEm7ZAF94nC4Gn +pFjcmkQoG6Azt//VF0wRY4jk3XVyeXApc5/pIHNDCgM7RHC0t3/n09MP1zcOqbBTCq4 i3Tk2k54/ulsD/shyyuDtAuNoEr780BGvRsgUIRBrDkv85kHdd9agtTt8xwDLtDHUOvF utSNm+gDItTNjIVJhN0eHPY5WKSp9KdQQG1/xhZXvld6X3bBKNzSfw+ToldG3Vmv5Mpl Hk/g== X-Received: by 10.68.197.72 with SMTP id is8mr33369744pbc.17.1423526237004; Mon, 09 Feb 2015 15:57:17 -0800 (PST) MIME-Version: 1.0 In-Reply-To: <54d94307$0$12998$c3e8da3$5496439d@news.astraweb.com> References: <54d94307$0$12998$c3e8da3$5496439d@news.astraweb.com> From: Ian Kelly Date: Mon, 9 Feb 2015 16:56:36 -0700 Subject: Re: __next__ and StopIteration To: Python Content-Type: text/plain; charset=UTF-8 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 41 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1423526240 news.xs4all.nl 2860 [2001:888:2000:d::a6]:46820 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:85411 On Mon, Feb 9, 2015 at 4:30 PM, Steven D'Aprano wrote: > The way you write iterators is like this: > > > Method 1 (the hard way): > > - Give your class an __iter__ method which simply returns self: > > def __iter__(self): > return self > > - Give your class a __next__ method (`next` in Python 2) which *returns* a > value. You will need to track which value to return yourself. It must raise > StopIteration when there are no more values to return. Don't use yield. > > def __next__(self): > value = self.value > if value is None: > raise StopIteration > self.value = self.calculate_the_next_value() > return value > > Your class is itself an iterator. This is an anti-pattern, so don't even suggest it. Iterables should never be their own iterators. Otherwise, your iterable can only be iterated over once! The proper version of the "hard way" is: 1) The __iter__ method of the iterable constructs a new iterator instance and returns it. 2) The __iter__ method of the *iterator* simply returns itself. 3) The __next__ method of the iterator tracks the current value and returns the next value. Note that the iterator should never store the iterable's data internally, unless the iterable is immutable and the calculation is trivial (e.g. a range object). Instead, it should determine the next value by referring to its source iterable.