The last call is every time true, because it's a generator expression.
g = (name in s for name in ('Bob', 'Ed'))
print(g) # Nothing is evaluated, it evaluates lazy
print(next(g))
print(next(g))
print(next(g)) # this will raise a StopIteration
Python supports following shortcuts:
- List comprehension, which makes a new list
[char for char in 'An Object which is iterable']
- Dict comprehension, which makes a new dict. The order is not preserved.
[n: char for n, char in enumerare('An Object which is iterable')]
# using here enumerate just for demonstration. If you want to count Elements in an iterable, just use collections.Counter
# collections.Counter('An Object which is iterable')
- Set comprehension which makes a new set. A set is a collection of elements, which are Unique. The order is not preserved.
{char for char in 'An Object which is iterable'}
# for example, you'll see the whitespace only one time
- Generator expression, which makes a generator. A generator is only executed when iterating over it. The state between iterations is saved in the generator.
g = (char for char in 'An Object which is iterable')
for c in g:
print(g)
# or written as a function
def gen():
for c in 'An Object which is iterable':
yield c # yield keyword makes a generator
for c in gen():
print(c)
Now we come to the point that,
all()
and
any()
, takes iterables and valuates to
bool(element)
all([True, True, True]) == True
all([True, False, True]) == False # all elements have to be checked
any([False, False, True]) == True # iterates till end has been reached
any([False, True, False]) == True # stops after second iteration
You can also pass a generator expression functions, if they are the only argument. In this case you don't have to use the parenthesis twice.
any((e for e in [False])) # this is valid
any(e for e in [False]) # this is valid
If you have a function, which takes more than one argument, you have to use parenthesis for a generator expression:
def foo(iterable, start):
for index, element in enumerate(iterable, start):
print(index, element)
foo((word for word in ['Hello' ,'World']), 1) # this is valid
foo((word for word in ['Hello' ,'World']), 1)
# SyntaxError: Generator expression must be parenthesized if not sole argument
Install ipython for Python3, which gives you better tabulator completion.
Then play around inside the repl.
In [1]: s = 'BobTom'
In [2]: any(name in s for name in ('Bob', 'Ed'))
Out[2]: True
In [3]: all(name in s for name in ('Bob', 'Ed'))
Out[3]: False
In [4]: (name in s for name in ('Bob', 'Ed'))
Out[4]: <generator object <genexpr> at 0x7f916f882c50>
In [5]: bool(name in s for name in ('Bob', 'Ed'))
Out[5]: True
In [6]: bool([])
Out[6]: False
In [8]: bool(tuple())
Out[8]: False
In [9]: bool('')
Out[9]: False
In [10]: bool('Foo')
Out[10]: True
In [11]: bool('False')
Out[11]: True
In [12]: bool('0')
Out[12]: True
In [13]: [name in s for name in ('Bob', 'Ed')]
Out[13]: [True, False]
In [14]: {name in s for name in ('Bob', 'Ed')}
Out[14]: {False, True}
In [15]: {name: name in s for name in ('Bob', 'Ed')}
Out[15]: {'Bob': True, 'Ed': False}
In [16]: (name in s for name in ('Bob', 'Ed'))
I hope this explains the use of list/dict/set comprehensions and generator expressions a little bit.
When you're using the if statement, it evaluates the bool. The object itself decides what it should return when __bool__() is called.
When calling bool(the_object)
- empty string returns False
- empty list returns False
- empty tuple returns False
- None returns False
- 0 returns False
- -1 returns True
- 1 returns True
- empty dict returns False
- empty set returns False
- normally all container types should return false, if they are empty
- a function returns True
def foo():
pass
bool(foo)
- a generator returns True
def gen():
yield 1
bool(gen)
- a class returns True
class Foo:
pass
bool(Foo)
You want to avoid the use of the three last examples. I am not sure about any use case to check the truthiness of a function, generator, class...
But you can do it accidentally, which gives you some output without an error, which leads to wrong conclusions.