Jul-22-2017, 09:09 AM
The last call is every time true, because it's a generator expression.
Now we come to the point that,
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.
Then play around inside the repl.
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)
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.
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 StopIterationPython 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 validIf 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 argumentInstall 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.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
All humans together. We don't need politicians!