I have the following problem with python\'s \"all\" and generators:
G = (a for a in [0,1])
all(list(G)) # returns False - as I expected
B
Aha!
Does Python(x,y) happen to import numpy? [It looks like it.]
Python 2.7.2 (v2.7.2:8527427914a2, Jun 11 2011, 15:22:34)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>> G = (a for a in [0,1])
>>> all(G)
False
>>> from numpy import all
>>>
>>> G = (a for a in [0,1])
>>> all(G)
True
>>>
Here's an explanation by Robert Kern:
It [all --ed] works on arrays and things it can turn into arrays by calling the C API equivalent of numpy.asarray(). There's a ton of magic and special cases in asarray() in order to interpret nested Python sequences as arrays. That magic works fairly well when we have sequences with known lengths; it fails utterly when given an arbitrary iterator of unknown length. So we punt. Unfortunately, what happens then is that asarray() sees an object that it can't interpret as a sequence to turn into a real array, so it makes a rank-0 array with the iterator object as the value. This evaluates to True.
I found out in python 3.2.3 if the value 0 is in the list all() will return False.
for all() to work you have to avoid having a zero in the iteration list.
It leads me to believe that zero is used as an end for the iteration.
Python 3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)] on win32
print(all([])) # prints True
print(all([0])) # prints False
print(all([2, 3])) # prints True
print(all([2, 3, 0])) # prints False
>>> G = (a for a in [0,1])
>>> all(list(G))
False
>>> G = (a for a in [0,1])
>>> all(G)
False
No True
. However:
>>> G = (a for a in [0,1])
>>> all(list(G))
False
>>> all(G)
True
>>> all([])
True
If you call all
a second time on the generator, you'll get True
, as there are no False
items left in the generator. As you can see, any empty sequence will work the same.
For this particular example, all
short-circuits, so you have 1
left to be generated after it returns False
because of the leading 0
(if you don't use list
) -- so it will return True
the second time despite not being empty.
"""
all(iterable)
Return True if all elements of the iterable are true (or if the iterable is
empty). Equivalent to:
def all(iterable):
for element in iterable:
if not element:# if element is zero returns False
return False
return True
"""
if you have '0' ( zeros in your iter) you will get False, when using all.
iters with zeros
l = [ x for x in range(10)]
l1 = range(10)
g = (x for x in range(10))
d = {k: v for k, v in zip(range(10), range(10)) }
t = tuple(l)
s = set(l)
for i in [ l , l1, g , d , t , s]:
print(type(i), i , "is iter " , all(i))
Out put :
<class 'list'> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] is iter False
<class 'range'> range(0, 10) is iter False
<class 'generator'> <generator object <genexpr> at 0x102a7d938> is iter False
<class 'dict'> {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9} is iter False
<class 'tuple'> (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) is iter False
<class 'set'> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} is iter False
iters without zeros
l = [ x for x in range(1, 10)]
l1 = range(1, 10)
g = (x for x in range(1, 10))
d = {k: v for k, v in zip(range(1, 10), range(1, 10)) }
t = tuple(l)
s = set(l)
for i in [ l , l1, g , d , t , s]:
print(type(i), i , "is iter " , all(i))
Out put :
<class 'list'> [1, 2, 3, 4, 5, 6, 7, 8, 9] is iter True
<class 'range'> range(1, 10) is iter True
<class 'generator'> <generator object <genexpr> at 0x102a7d938> is iter True
<class 'dict'> {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9} is
iter True
<class 'tuple'> (1, 2, 3, 4, 5, 6, 7, 8, 9) is iter True
<class 'set'> {1, 2, 3, 4, 5, 6, 7, 8, 9} is iter True
No, it doesn't. The following snippet returns False
G = (a for a in [0,1])
all(G) # returns False
Are you perhaps doing the following
G = (a for a in [0,1])
all(list(G)) # returns False
all(G) # returns True!
In that case, you are exhausting the generator G
when you construct the list, so the final call to all(G)
is over an empty generator and hence returns the equivalent of all([])
-> True
.
A generator can't be used more than once.