🐍 Python - Equality
Equality
Updated at 2018-06-11 01:00
is checks for identity while == checks for equality.
a = [1, 2, 3]
b = a
c = list(a)
assert a == b
assert a is b
assert a == c
assert a is not c
Any content or value makes an object truthy.
assert not False
assert True
assert not None # None is falsy
assert not () # empty tuple is falsy
assert (None,) # any content makes tuple truthy
assert not [] # empty list is falsy
assert [None] # any content make list truthy
assert not set() # empty set is falsy
assert {None} # any content makes set truthy
assert not {} # empty dict is falsy
assert {'key': None} # any content makes dict truthy
assert not '' # empty str is falsy
assert ' ' # any content makes str truthy
assert not 0 # zero integer is falsy
assert -123 and 123 # non-zero integers are truthy
assert not 0.0 # zero float is falsy
assert -.1 and 12.3 # non-zero floats are truthy
a == b is syntactical sugar for a.eq(b)``
Always use is to check for singletons like None. is is less error prone and faster as it can't be overloaded like ==.
from typing import Optional
def greet(name: Optional[str] = None):
if name is None:
return 'Hello!'
else:
return f'Hello, {name}!'
assert greet() == 'Hello!'
assert greet('Ruksi') == 'Hello, Ruksi!'
Never use is with strings or integers. It usually works because of interning, but is undocumented implementation quirk.
s1 = 'ABC'
s2 = 'ABC'
assert s1 is s2 # BAD, never do this even if it works for now
Prefer isinstance(obj, cls) over type(obj) == cls. And make sure cls is always an abstract class which's metaclass derives from abc.ABCMeta. There are plenty of useful abstract classes in typing and numbers, although int and float are usually the best.
import numbers
from typing import Callable, Collection, Container, Hashable, \
Iterable, MutableSequence, Sequence, Sized
assert isinstance(list(), Collection)
assert isinstance(list(), Sized)
assert isinstance(list(), Container)
assert isinstance(list(), Sequence)
assert isinstance(list(), MutableSequence)
assert isinstance(list(), Iterable)
assert not isinstance(list(), Hashable)
def greet() -> str:
return 'Hello!'
assert isinstance(greet, Callable)
assert isinstance(lambda x: x + 1, Callable)
assert isinstance(123, int)
assert not isinstance(123, float)
assert isinstance(1.23, float)
assert not isinstance(1.23, int)
assert isinstance(123, numbers.Number)
assert isinstance(123, numbers.Complex)
assert isinstance(123, numbers.Real)
assert isinstance(123, numbers.Rational) # different than decimal.Decimal
assert isinstance(123, numbers.Integral)
assert isinstance(1.23, numbers.Number)
assert not isinstance(1.23, numbers.Integral)
assert isinstance(True, numbers.Number) # Booleans are numbers 1 and 0
assert isinstance(False, numbers.Number)
Source
- Python Tricks The Book, Dan Bader
- Fluent Python, Luciano Ramalho