I managed to come up with an approach using map
that hasn't been given yet
tl;dr
def all_none(l):
return not any(map(None.__ne__, l))
all_none([None, None, None]) # -> True
all_none([None, None, 8]) # -> False
explanation
The use of None.__ne__
is bit weirder than you'd expect at first glance. This method returns a NotImplementedType
object when given something that isn't None.
You'd be hoping that NotImplemented
would be a stand-in for False
, however it's truthy too! This means that using None.__eq__
across a collection will produce thruthy values for everything.
list(map(None.__eq__, [None, None, 8]))
# -> [True, True, NotImplemented]
all(list(map(None.__eq__, [None, None, 8])))
# -> True
From the Python Docs:
By default, an object is considered true unless its class defines
either a bool() method that returns False or a len() method
that returns zero
Instead, None.__ne__
returns False
for any None
elements, and a
NotImplementedType
object for anything else:
list(map(None.__ne__, [None, None, 8]))
# -> [False, False, NotImplemented]
Using this, you can check if any
elements are not None
which will return True
. I like to think of this as 2 separate methods if that helps with the mental negation gymnastics.
def contains_truthy(l):
return any(map(None.__ne__, l))
def all_none(l):
return not contains_truthy(l)
I haven't done any benchmarking with this, but as mentioned by others in this thread, not any
will produce fast results.