[Python-ideas] Consider making enumerate a sequence if its argument is a sequence

Akira Li 4kir4.1i at gmail.com
Fri Oct 2 08:30:23 CEST 2015


Steven D'Aprano <steve at pearwood.info> writes:

> On Thu, Oct 01, 2015 at 04:13:37PM -0700, Chris Barker wrote:
>> On Thu, Oct 1, 2015 at 12:37 PM, Steven D'Aprano <steve at pearwood.info>
>> wrote:
>> 
>> > This makes a difference. Just a few days ago, somebody mis-reported a
>> > supposed "bug" in all() and any(). For example:
>> >
>> > values = (x%5 == 3 for x in range(8))
>> > print(list(values))
>> > print(all(values))  # should return False
>> >
>> > Obvious error is obvious: having printed out the values from the
>> > generator expression, values is now exhausted, and all() of the empty
>> > set is True (vacuous truth). The difference between general iterables
>> > which may or may not be one-shot iterators, and those which are
>> > definitely not iterators, is not always just an implementation detail.
>> 
>> 
>> they used a generator expression, when they clearly wanted a list
>> comprehension -- so yes, it matters what they were getting, I don't know
>> that adding more vocabulary would help prevent people from making that
>> mistake...
>> 
>> if they had been smart enough to call the list() again, before claiming
>> there was a bug in all -- it may have explained itself.
>
> You're missing the point. Don't focus on the fact that the bug was in 
> their understanding of what their code did. Let's just pretend that 
> their *intentional* algorithm was:
>
> def alg(iterable):
>     print(list(iterable))
>     print(all(iterable))
>
> and for the sake of bring this never-ending thread to an end, let's 
> agree for the sake of argument that it cannot be re-written in any other 
> way.
>
> Since the semantics of the function are intentional and correct, the 
> parameter is named misleadingly. *iterable* is not sufficiently precise, 
> because the function does not accept any old iterable -- it fails to 
> work correctly on *iterators*, are a sub-kind of iterable.

list(iterable) does not work for infinite iterables.
set(iterable) does not work for iterables that yield non-hashable items.
dict(iterable) does not work for iterables that do not yield key,value
pairs.

Each builtin specifies what type of iterable it accepts but the
parameter IS called *iterable*. Are you suggesting to rename the
parameters?

> If you want a more practical example, any algorithm which needs to 
> iterate over an interable two or more times needs to specify "iterable 
> which is not an iterator".

If the intent is to write:

  def alg(iterable):
      seq = list(iterable)
      print(seq)
      print(all(seq))

You could say that the 1st alg() accepts a "repeatable deterministic iterable".



More information about the Python-ideas mailing list