True
is bool
which is inherits from integer and is equal to 1
(but is not the exact same as 1
).
help(bool)
Output:
class bool(int)
| bool(x) -> bool
|
| Returns True when the argument x is true, False otherwise.
| The builtins True and False are the only two instances of the class bool.
| The class bool is a subclass of the class int, and cannot be subclassed.
|
| Method resolution order:
| bool
| int
| object
But because True
inherits from int
, we should be able to do everything with a bool
that we can with an int
!
print(5 + True) # > 6
print(17 - False) # > 17
print(15//True) # > 15
print(10/False) # > raises ZeroDivisionError since False "=" 0
To answer your main question however, which is explaining why 1 in (True, None)
evaluates to True
is because the in
operator works by checking equality
(with ==
) and not object identity (with is
). The None
in your statement has nothing to do with it; it could be any object and your statement would still evaluate to True
.
print(1 == True) # > True
print(1 is True) # > False
True
is 1
but with a little extra fluff added to it from the bool
methods
I think a pythonic way of achieving what you're after is to check if the object's identity is contained in the list (which is what you suggested, but we can generalize it a bit)
id(1) in [id(x) for x in [True, None]] # > False
Essentially this is just a stronger version of the in
operator. We can write it as a function:
def stronger_in(val, it):
return id(val) in [id(_) for _ in it]
print(stronger_in(1, (True, None)) # > False