When you create a custom class and try to
print an instance of it, Python gives you something like <__main__.Dog object at 0x7f...>. It tells you the type and memory address, but not what your data actually is. That's helpful for debugging in some cases, but mostly just noise.__str__ vs __repr__
class Dog:
def __init__(self, name):
self.name = name
dog = Dog('Rex')
print(dog) # <__main__.Dog object at 0x...>
str(dog) # same unhelpful string__str__ is what print() and str() use. It should be a human-friendly summary of the object.__repr__ is meant for developers: an unambiguous representation, ideally something you could copy-paste back into Python to recreate the object.class Dog:
def __init__(self, name):
self.name = name
def __str__(self):
return f'Dog({self.name})'
dog = Dog('Rex')
print(dog) # Dog(Rex)__eq__: comparing objects by data
class Dog:
def __init__(self, name):
self.name = name
d1 = Dog('Rex')
d2 = Dog('Rex')
print(d1 == d2) # False! They are different objects in memory.By default,
== checks identity (same object), not equality of contents. To compare by data, implement __eq__. It receives the other object and returns True or False, or NotImplemented when it doesn't know how to compare itself with that kind of object.class Dog:
def __init__(self, name):
self.name = name
def __eq__(self, other):
if not isinstance(other, Dog):
return NotImplemented
return self.name == other.name
d1 = Dog('Rex')
d2 = Dog('Rex')
print(d1 == d2) # True__len__: how many items?
class Playlist:
def __init__(self, songs):
self.songs = list(songs)
p = Playlist(['A', 'B'])
print(len(p)) # TypeError: object of type 'Playlist' has no len()len() calls __len__(). If your class wraps a collection, implement it so you can ask "how big is this?" directly.