Daily Rant: all() and any() on empty iterables
>>> all([])
True
>>> any([])
False
This may or may not be counter-intuitive. If it is, here is the simple explanation I like:
For a non-empty iterable X, you can consider all(X) to be equivalent to X[0] and all(X[1:])
When you expand everything, you get X[0] and X[1] and ... and all([]), notice how things will collapse if all([]) return False, because if it is the case, all() will never return True.
In the same way, you can consider any(X) to be equivalent to X[0] or any(X[1:])
When you expand everything, you get X[0] or X[1] or ... or any([]), notice how things will collapse if any([]) return True, because if it is the case, any() will never return False.
This is neither a good nor correct explanation, because one can argue that they can define all() and any() operator with a non-empty iterable as the base of its recursive cause. I am not even sure if a set with negative numbers of elements is a thing, which will spark even more debate.
More about this at Neizod's blog: ตรรกะและการเขียนโค้ดจากวลี not all ~ neizod's speculation