Defining Classes and Creating Instances
The class keyword creates a new type in Python, not just a container for code.
Try it: Classes, Instances and Attributes
How a class creates instances with __init__ and self, why an attribute read checks the instance's __dict__ before the class, why assigning through an instance never changes the class, how a class-level list is shared by every instance, and why obj.method(x) is Class.method(obj, x).
How it works
- Dog(...) makes a new, empty instance and calls Dog.__init__(new_object, ...); self.name = ... stores into that object's __dict__.
- Reading obj.attr looks in obj.__dict__ first, then in the class.
- Assigning obj.attr = value always writes obj.__dict__, so it shadows a class attribute for that one object only.
- Mutating a class-level list (self.tricks.append) changes the one list every instance shares.
- obj.method is found on the class and bound to obj, so obj.method(x) runs Class.method(obj, x).
Default run (30 steps): Ready: class Dog and the statements you picked. Watch where each attribute is found and where each assignment writes. … Finished. Printed: ['sit'] / Wolf / Canis familiaris / Fido is 5.
Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. Object numbers are illustrative, not real id() values.
Loading the simulation…
From Definition to Object
Python does not treat a class as merely a container for related code. When you define a class, the class keyword creates a new type. When you later call that class, Python creates an instance, which is an object belonging to that new type.
The PartyAnimal Type
Consider a class named PartyAnimal. Its definition describes an __init__ method that sets up an attribute named x and a party method that increments x and prints a message. The important point is not only what these members do. The definition also introduces PartyAnimal as a new type that Python can recognize.
In this example, PartyAnimal is the custom type and an is an instance of that type. Calling PartyAnimal() creates the instance. The instance has the x attribute and the party method described by the class.
What do you think happens?
What do you expect type(an) to identify?
Reveal answer
PartyAnimal
The object an was created by calling PartyAnimal(), so its type is the custom type PartyAnimal rather than a built-in type such as int or str.
Built-In and Custom Types
| Object | Type | How the type is provided |
|---|---|---|
| 5 | int | Built in to Python |
| 'Alice' | str | Built in to Python |
| an | PartyAnimal | Created with the class keyword |
Built-in objects and custom-class instances both have types.
Python provides built-in types such as int and str, but it also lets you introduce your own types. An instance of PartyAnimal is therefore comparable at the type level to the integer object 5: both are objects, and each belongs to a recognized type. Their types are different because one is int and the other is PartyAnimal.
Reading an Object with type()
The type() function returns the class of an object. It can identify the type of a built-in object such as 5 or 'Alice', and it can also identify the type of an instance created from a custom class.
class PartyAnimal:
def __init__(self):
self.x = 0
def party(self):
self.x = self.x + 1
an = PartyAnimal()
print(type(5))
print(type(an))
print(type(an.x))
print(type(an.party))- 1Python identifies 5 as an int object.
- 2Python identifies an as an instance of PartyAnimal.
- 3Python examines the value stored in
an.xand identifies it as an int. - 4Python identifies an.party as a method.
- The class definition introduces PartyAnimal as a custom type.
- Calling
PartyAnimal()creates the instance an. - The value 5 has type int.
- The instance an has type PartyAnimal.
- The attribute x contains an integer, so its type is int.
- The attribute party refers to a method.
Exploring Members with dir()
The dir() function lists the attributes and methods available on an object. For an instance such as an, the list includes members defined for the custom class, such as x and party, along with special methods that Python provides to the class.
The result of dir(an) is a list of names, not a description of what each member does. In the PartyAnimal example, finding x confirms that the instance has the attribute established by __init__. Finding party confirms that the instance exposes the method defined by the class. The same listing also contains special methods automatically associated with the class.
Separate Instances
A class can create more than one instance. If you create an2 with PartyAnimal(), both an and an2 have type PartyAnimal, and both have an x attribute and a party method. They are nevertheless separate objects with separate data. The class identifies what kind of objects they are; each instance is an individual object of that type.
Two Instances of One Custom Type
Track the relationship between PartyAnimal, an, and an2.
- 1Define the type
The class definition creates the custom type PartyAnimal.
- 2Create the first instance
Calling
PartyAnimal()creates an, an object whose type is PartyAnimal. - 3Create the second instance
Calling
PartyAnimal()again creates an2, another object whose type is PartyAnimal. - 4Compare their data
Both instances have an x attribute and a party method, but they are separate objects with separate data.
an and an2 share the same custom type, PartyAnimal, while remaining distinct instances.
Common Inspection Mistakes
Common mistake Treating a class as only a code container
What it looks likeThinking of PartyAnimal as merely a place where party is stored.
Why it failsThe class keyword creates a new type that Python recognizes.
Do this insteadDescribe PartyAnimal as a custom type and an as an instance of that type.
Common mistake Expecting type(an) to return a built-in type
What it looks likeExpecting type(an) to be int or str.Why it failsan was created by calling
PartyAnimal(), so its type is PartyAnimal.Do this insteadUse type(an) to identify the custom class used to create the instance.
Common mistake Assuming dir() only lists members written by the programmer
What it looks likeExpecting dir(an) to contain only x and party.
Why it failsdir()also lists special methods that Python provides on the object.Do this insteadTreat the result as a complete listing of available attributes and methods, including special methods.
Common mistake Confusing an instance with one of its attributes
What it looks likeUsing the type of an.x as if it were the type of an.
Why it failsan is a PartyAnimal instance, while
an.xis an integer attribute.Do this insteadApply type() to the specific object whose type you want to inspect.
Check Your Understanding
Suppose a class named Book is defined and then an instance named first_book is created by calling Book(). Predict the result of type(first_book). Then describe what you would look for in dir(first_book) to confirm that the instance exposes a class-defined attribute or method.
Hints
- The type is determined by the class used to create the instance.
dir()lists names available on the object, including user-defined attributes and methods.- Do not expect
dir()to contain only names written in the class definition; special methods can also appear.
- 1A class definition introduces a new type. Calling the class creates an instance of that type. The
type()function identifies the class of an object, whiledir()lists the attributes and methods available on it. Custom-class instances are genuine Python objects with their own custom type, just as 5 is an object of type int.
Key Takeaways
- The class keyword creates a new custom type in Python.
- Calling a class creates an instance of that type.
type()reports the class of an object, including an instance of a custom class.dir()lists the attributes and methods available on an object, including special methods.- Multiple instances can share one custom type while remaining separate objects with separate data.