The Python Language Reference, Release 3.9.5 6.10.2 Membership test operations 6.10.3 Identity comparisons 6.11 Boolean operations 4 Due to automatic garbage-collection, free lists, and the dynamic nature of descriptors, you may notice seemingly unusual behaviour in certain uses of the is operator, like those involving comparisons between instance methods, or constants. Check their documentation for more info. 79 6.11. Boolean operations Note that neither$_{and}$nor$_{or}$ restrict the value and type they return to$_{False}$ and$_{True}$, but rather return the last evaluated argument. This is sometimes useful, e.g., if$_{s}$ is a string that should be replaced by a default value if it is empty, the expression$_{s or 'foo'}$ yields the desired value. Because$_{not}$has to create a new value, it returns a boolean value regardless of the type of its argument (for example,$_{not 'foo'}$ produces$_{False}$ rather than$_{''}$ .) The expression$_{x or y}$ first evaluates x ; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned. The expression$_{x and y}$first evaluates x ; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned. The operator$_{not}$yields$_{True}$ if its argument is false,$_{False}$ otherwise. In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false:$_{False}$,$_{None}$ , numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets). All other values are interpreted as true. User-defined objects can customize their truth value by providing a$_{__bool__()}$ method. The operators$_{is}$ and$_{is not}$ test for an object’s identity:$_{x is y}$ is true if and only if x and y are the same object. An Object’s identity is determined using the$_{id()}$ function.$_{x is not y}$yields the inverse truth value. 4 The operator$_{not in}$ is defined to have the inverse truth value of$_{in}$. Lastly, the old-style iteration protocol is tried: if a class defines$_{__getitem__()}$ ,$_{x in y}$ is$_{True}$ if and only if there is a non-negative integer index i such that x is y[i] or x == y[i] , and no lower integer index raises the IndexError exception. (If any other exception is raised, it is as if in raised that exception). For user-defined classes which do not define$_{__contains__()}$ but do define$_{__iter__()}$ ,$_{x in y}$ is$_{True}$ if some value$_{z}$ , for which the expression$_{x is z or x == z}$is true, is produced while iterating over$_{y}$. If an exception is raised during the iteration, it is as if$_{in}$ raised that exception. For user-defined classes which define the __contains__() method, x in y returns True if y. __contains__(x) returns a true value, and$_{False}$ otherwise. For the string and bytes types, x in y is True if and only if x is a substring of y . An equivalent test is y.find(x) != -1 . Empty strings are always considered to be a substring of any other string, so "" in "abc" will return $_{True}$. The operators$_{in}$ and$_{not in}$ test for membership.$_{x in s}$ evaluates to$_{True}$ if x is a member of s , and$_{False}$ otherwise.$_{x not in s}$returns the negation of$_{x in s}$. All built-in sequences and set types support this as well as dictionary, for which in tests whether the dictionary has a given key. For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y) . or_test ::= and_test | or_test "or" and_test and_test ::= not_test | and_test "and" not_test not_test ::= comparison | "not" not_test