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