Special Methods and Operator Overloading
The class keyword creates a new type in Python, not just a container for code.
From Class Definition to New Type
A class in Python is more than a container for related code. The class keyword creates a new type: a new category of object that Python recognizes. When you create an instance from that class, the instance belongs to the new type in the same broad sense that 5 belongs to the built-in type int and a text value belongs to the built-in type str.
Operator Expressions and Special Methods
Special methods are among the methods that Python makes available on objects. They are listed by dir() along with user-defined attributes and methods. These methods are connected with the behavior Python can provide for objects. In operator overloading, an expression such as obj + other is associated with a special method such as __add__. The important inspection skill is to recognize that this special method is part of the object's available behavior, even though its name uses Python's double-underscore convention.
Inspecting the Instance Type
What do you think happens?
Suppose an is an instance created from the custom class PartyAnimal. What should type(an) identify?
Reveal answer
Answer: PartyAnimal
An instance created from PartyAnimal is an object of that class's type. It is not an integer or a string merely because it may contain an integer or string attribute.
Reading the Types in PartyAnimal
An instance named an comes from the custom class PartyAnimal. The instance has an attribute x and a method party. What types should inspection identify?
Inspect the instance: type(an) identifies the class of the instance, so the result identifies PartyAnimal.
Inspect the attribute: The attribute x stores an integer, so type(an.x) identifies int.
Inspect the method: The attribute party refers to a method, so type(an.party) identifies method.
The instance has type PartyAnimal, its x attribute has type int, and its party attribute has type method.
The same inspection rule applies to built-in and custom objects. type(5) identifies int, type('Alice') identifies str, and type(an) identifies PartyAnimal. The result shows the type of the object itself, not the type of every value stored inside it.
Reading dir() Results
The dir() function lists the attributes and methods available on an object. For a PartyAnimal instance named an, the result includes the user-defined attribute x and the user-defined method party. It also includes many special methods that Python automatically adds to every class. Therefore, dir(an) gives a broader view than a list of only the names you wrote yourself.
Use type() when you need to identify what kind of object you are examining. Use dir() when you need to inspect the names available on that object. Read the two results together: type() identifies the object's category, while dir() exposes available attributes and methods.
Separate Instances, Separate Data
A class can produce more than one instance. If an2 is created from PartyAnimal, both an and an2 have type PartyAnimal. They are nevertheless separate objects with separate data. Each instance has its own x attribute and its own party method available through the instance.
| Object | Type identified by type() | What inspection tells you |
|---|---|---|
| an | PartyAnimal | A custom-class instance with its available attributes and methods |
| an2 | PartyAnimal | Another custom-class instance with separate data |
| 5 | int | A value of a built-in type |
| Alice | str | A value of a built-in type |
Mistakes in Object Inspection
Thinking a class only organizes code
The class keyword creates a new type, and instances created from it are objects of that type.
Fix:
Describe PartyAnimal as a custom type and an instance created from it as an object of type PartyAnimal.Expecting type(an) to report the type of an attribute
type() reports the type of the object passed to it. The instance is PartyAnimal; the separate expression an.x has type int.
Fix:
Inspect type(an) and type(an.x) as two different questions.Assuming dir() lists only names written by the programmer
dir() lists user-defined attributes and methods as well as special methods automatically available on the class.
Fix:
Expect dir(instance) to contain both your own members and special methods.Assuming two instances are the same object because their types match
Instances can have the same type while remaining separate objects with separate data.
Fix:
Distinguish the shared class type from each instance's separate data.
Practice the Inspection Habit
A custom class creates an instance named sample. The instance has a user-defined attribute count, a user-defined method display, and special methods visible through inspection. Explain what each of these inspections is intended to reveal: type(sample), type(sample.count), type(sample.display), and dir(sample).
Hints
- Ask which object is passed to type() each time.
- Separate the instance from its attribute and method.
- Remember that dir() includes user-defined members and special methods.
- A class definition introduces a new type. Instances created from that class are objects of that type, just as built-in values are objects of types such as int and str. Use type() to identify the class of a particular object. Use dir() to inspect the object's available attributes and methods, including special methods. When you see a special method such as __add__ in that inspection, connect it with the behavior associated with an operator expression such as obj + other.
Key Takeaways
- The class keyword creates a new custom type in Python.
- An instance created from a class has that class as its type.
- type() identifies the type of the object supplied to it, not the type of an unrelated attribute inside the object.
- dir() lists user-defined attributes and methods together with special methods available on the object.
- Instances can share a class type while remaining separate objects with separate data.