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.