[Python-checkins] CVS: python/nondist/peps pep-0234.txt,1.8,1.9
Guido van Rossum
gvanrossum@users.sourceforge.net
Mon, 30 Apr 2001 19:04:30 -0700
Update of /cvsroot/python/python/nondist/peps
In directory usw-pr-cvs1:/tmp/cvs-serv8447
Modified Files:
pep-0234.txt
Log Message:
Moved all the discussion items together at the end, in two sections
"Open Issues" and "Resolved Issues".
Index: pep-0234.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0234.txt,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -r1.8 -r1.9
*** pep-0234.txt 2001/04/27 15:33:02 1.8
--- pep-0234.txt 2001/05/01 02:04:28 1.9
***************
*** 98,118 ****
use an iterator (as opposed to a sequence) in a for loop.
- Discussion: should the next() method be renamed to __next__()?
- Every other method corresponding to a tp_<something> slot has a
- special name. On the other hand, this would suggest that there
- should also be a primitive operation next(x) that would call
- x.__next__(), and this just looks like adding complexity without
- benefit. So I think it's better to stick with next(). On the
- other hand, Marc-Andre Lemburg points out: "Even though .next()
- reads better, I think that we should stick to the convention that
- interpreter APIs use the __xxx__ naming scheme. Otherwise, people
- will have a hard time differentiating between user-level protocols
- and interpreter-level ones. AFAIK, .next() would be the first
- low-level API not using this convention." My (BDFL's) response:
- there are other important protocols with a user-level name
- (e.g. keys()), and I don't see the importance of this particular
- rule. BDFL pronouncement: this topic is closed. next() it is.
-
Python API Specification
--- 98,102 ----
***************
*** 151,183 ****
implement __iter__() returning itself.
- Discussion:
-
- - The name iter() is an abbreviation. Alternatives proposed
- include iterate(), harp(), traverse(), narrate().
-
- - Using the same name for two different operations (getting an
- iterator from an object and making an iterator for a function
- with an sentinel value) is somewhat ugly. I haven't seen a
- better name for the second operation though.
-
- - There's a bit of undefined behavior for iterators: once a
- particular iterator object has raised StopIteration, will it
- also raise StopIteration on all subsequent next() calls? Some
- say that it would be useful to require this, others say that it
- is useful to leave this open to individual iterators. Note that
- this may require an additional state bit for some iterator
- implementations (e.g. function-wrapping iterators).
-
- - Some folks have requested the ability to restart an iterator. I
- believe this should be dealt with by calling iter() on a
- sequence repeatedly, not by the iterator protocol itself.
-
- - It was originally proposed that rather than having a next()
- method, an iterator object should simply be callable. This was
- rejected in favor of an explicit next() method. The reason is
- clarity: if you don't know the code very well, "x = s()" does
- not give a hint about what it does; but "x = s.next()" is pretty
- clear. BDFL pronouncement: this topic is closed. next() it is.
-
Dictionary Iterators
--- 135,138 ----
***************
*** 211,255 ****
as long as the restriction on modifications to the dictionary
(either by the loop or by another thread) are not violated.
-
- There is no doubt that the dict.has_keys(x) interpretation of "x
- in dict" is by far the most useful interpretation, probably the
- only useful one. There has been resistance against this because
- "x in list" checks whether x is present among the values, while
- the proposal makes "x in dict" check whether x is present among
- the keys. Given that the symmetry between lists and dictionaries
- is very weak, this argument does not have much weight.
-
- The main discussion focuses on whether
-
- for x in dict: ...
-
- should assign x the successive keys, values, or items of the
- dictionary. The symmetry between "if x in y" and "for x in y"
- suggests that it should iterate over keys. This symmetry has been
- observed by many independently and has even been used to "explain"
- one using the other. This is because for sequences, "if x in y"
- iterates over y comparing the iterated values to x. If we adopt
- both of the above proposals, this will also hold for
- dictionaries.
-
- The argument against making "for x in dict" iterate over the keys
- comes mostly from a practicality point of view: scans of the
- standard library show that there are about as many uses of "for x
- in dict.items()" as there are of "for x in dict.keys()", with the
- items() version having a small majority. Presumably many of the
- loops using keys() use the corresponding value anyway, by writing
- dict[x], so (the argument goes) by making both the key and value
- available, we could support the largest number of cases. While
- this is true, I (Guido) find the correspondence between "for x in
- dict" and "if x in dict" too compelling to break, and there's not
- much overhead in having to write dict[x] to explicitly get the
- value. We could also add methods to dictionaries that return
- different kinds of iterators, e.g.
-
- for key, value in dict.iteritems(): ...
-
- for value in dict.itervalues(): ...
! for key in dict.iterkeys(): ...
--- 166,175 ----
as long as the restriction on modifications to the dictionary
(either by the loop or by another thread) are not violated.
! If this proposal is accepted, it makes sense to recommend that
! other mappings, if they support iterators at all, should also
! iterate over the keys. However, this should not be taken as an
! absolute rule; specific applications may have different
! requirements.
***************
*** 310,313 ****
--- 230,366 ----
+ Open Issues
+
+ The following questions are still open.
+
+ - The name iter() is an abbreviation. Alternatives proposed
+ include iterate(), harp(), traverse(), narrate().
+
+ - Using the same name for two different operations (getting an
+ iterator from an object and making an iterator for a function
+ with an sentinel value) is somewhat ugly. I haven't seen a
+ better name for the second operation though.
+
+ - Once a particular iterator object has raised StopIteration, will
+ it also raise StopIteration on all subsequent next() calls?
+ Some say that it would be useful to require this, others say
+ that it is useful to leave this open to individual iterators.
+ Note that this may require an additional state bit for some
+ iterator implementations (e.g. function-wrapping iterators).
+
+ - Some folks have requested extensions of the iterator protocol,
+ e.g. prev() to get the previous item, current() to get the
+ current item again, finished() to test whether the iterator is
+ finished, and maybe even others, like rewind(), __len__(),
+ position().
+
+ While some of these are useful, many of these cannot easily be
+ implemented for all iterator types without adding arbitrary
+ buffering, and sometimes they can't be implemented at all (or
+ not reasonably). E.g. anything to do with reversing directions
+ can't be done when iterating over a file or function. Maybe a
+ separate PEP can be drafted to standardize the names for such
+ operations when the are implementable.
+
+ - There is still discussion about whether
+
+ for x in dict: ...
+
+ should assign x the successive keys, values, or items of the
+ dictionary. The symmetry between "if x in y" and "for x in y"
+ suggests that it should iterate over keys. This symmetry has been
+ observed by many independently and has even been used to "explain"
+ one using the other. This is because for sequences, "if x in y"
+ iterates over y comparing the iterated values to x. If we adopt
+ both of the above proposals, this will also hold for
+ dictionaries.
+
+ The argument against making "for x in dict" iterate over the keys
+ comes mostly from a practicality point of view: scans of the
+ standard library show that there are about as many uses of "for x
+ in dict.items()" as there are of "for x in dict.keys()", with the
+ items() version having a small majority. Presumably many of the
+ loops using keys() use the corresponding value anyway, by writing
+ dict[x], so (the argument goes) by making both the key and value
+ available, we could support the largest number of cases. While
+ this is true, I (Guido) find the correspondence between "for x in
+ dict" and "if x in dict" too compelling to break, and there's not
+ much overhead in having to write dict[x] to explicitly get the
+ value. We could also add methods to dictionaries that return
+ different kinds of iterators, e.g.
+
+ for key, value in dict.iteritems(): ...
+
+ for value in dict.itervalues(): ...
+
+ for key in dict.iterkeys(): ...
+
+
+ Resolved Issues
+
+ The following topics have been decided by consensus or BDFL
+ pronouncement.
+
+ - Two alternative spellings for next() have been proposed but
+ rejected: __next__(), because it corresponds to a type object
+ slot (tp_iternext); and __call__(), because this is the only
+ operation.
+
+ Arguments against __next__(): while many iterators are used in
+ for loops, it is expected that user code will also call next()
+ directly, so having to write __next__() is ugly; also, a
+ possible extension of the protocol would be to allow for prev(),
+ current() and reset() operations; surely we don't want to use
+ __prev__(), __current__(), __reset__().
+
+ Arguments against __call__() (the original proposal): taken out
+ of context, x() is not very readable, while x.next() is clear;
+ there's a danger that every special-purpose object wants to use
+ __call__() for its most common operation, causing more confusion
+ than clarity.
+
+ - Some folks have requested the ability to restart an iterator.
+ This should be dealt with by calling iter() on a sequence
+ repeatedly, not by the iterator protocol itself.
+
+ - It has been questioned whether an exception to signal the end of
+ the iteration isn't too expensive. Several alternatives for the
+ StopIteration exception have been proposed: a special value End
+ to signal the end, a function end() to test whether the iterator
+ is finished, even reusing the IndexError exception.
+
+ - A special value has the problem that if a sequence ever
+ contains that special value, a loop over that sequence will
+ end prematurely without any warning. If the experience with
+ null-terminated C strings hasn't taught us the problems this
+ can cause, imagine the trouble a Python introspection tool
+ would have iterating over a list of all built-in names,
+ assuming that the special End value was a built-in name!
+
+ - Calling an end() function would require two calls per
+ iteration. Two calls is much more expensive than one call
+ plus a test for an exception. Especially the time-critical
+ for loop can test very cheaply for an exception.
+
+ - Reusing IndexError can cause confusion because it can be a
+ genuine error, which would be masked by ending the loop
+ prematurely.
+
+ - Some have asked for a standard iterator type. Presumably all
+ iterators would have to be derived from this type. But this is
+ not the Python way: dictionaries are mappings because they
+ support __getitem__() and a handful other operations, not
+ because they are derived from an abstract mapping type.
+
+ - Regarding "if key in dict": there is no doubt that the
+ dict.has_keys(x) interpretation of "x in dict" is by far the
+ most useful interpretation, probably the only useful one. There
+ has been resistance against this because "x in list" checks
+ whether x is present among the values, while the proposal makes
+ "x in dict" check whether x is present among the keys. Given
+ that the symmetry between lists and dictionaries is very weak,
+ this argument does not have much weight.
+
+
Mailing Lists
***************
*** 321,324 ****
--- 374,378 ----
http://groups.yahoo.com/group/python-iter
+
Copyright