Python OOP Tutorial 1: Classes and Instances
Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Classes act as blueprints, while instances are the individual objects created from those blueprints.
Briefing
Python’s class system is presented as a practical way to bundle related data and behavior into reusable blueprints—especially when you need many similar objects with their own unique values. The tutorial’s core message is that classes let developers avoid repetitive, error-prone setup code by defining a single structure (a class) and then creating multiple independent objects (instances) from it.
A simple Employee class is introduced to model real-world entities. The distinction between a class and an instance is made early: the class acts as a blueprint, while each Employee created from it becomes a separate instance with its own identity in memory. Two employees created from the same Employee class are shown as distinct objects, even though they share the same underlying structure.
The tutorial then focuses on instance variables—data unique to each object. It demonstrates the manual approach first: assigning attributes like first name, last name, email, and pay directly to each employee instance. That method works, but it quickly becomes verbose and easy to get wrong (the example shows a mistake where one employee’s email assignment isn’t updated correctly). The takeaway is that manually setting attributes defeats much of the benefit of using classes.
To automate initialization, the tutorial introduces Python’s special __init__ method. This method runs automatically whenever a new instance is created. Inside __init__, the instance is received as the first argument (by convention named self), followed by the values needed to set up the object. The tutorial builds the email from first and last names and assigns pay, first, and last to instance variables like self.first, self.last, self.pay, and self.email. With __init__ in place, creating new employees becomes as simple as passing first name, last name, and pay—Python handles the rest.
Next comes behavior: methods. The tutorial shows how printing an employee’s full name can be done repeatedly with string formatting outside the class, but that repetition is exactly what methods are meant to eliminate. A full_name method is added to the Employee class, returning a combined string using self.first and self.last. Calling employee1.full_name() and employee2.full_name() produces the correct result for each instance.
A common pitfall is highlighted: forgetting the self parameter in a method definition. Without self, calling the method triggers a TypeError because Python still passes the instance automatically, meaning the method signature no longer matches what Python provides. The tutorial also compares calling the method on an instance (employee1.full_name()) versus calling it on the class (Employee.full_name(employee1)), clarifying how self gets supplied behind the scenes.
By the end, the foundational pieces are in place: creating classes, understanding class vs instance, initializing instance variables with __init__, and defining instance methods that operate correctly across all objects created from the same class. The next step previewed is class variables and how they differ from instance variables.
Cornell Notes
The tutorial builds an Employee class to show how Python OOP reduces repetition and mistakes. It distinguishes a class (blueprint) from instances (individual objects with separate memory identities). Instance variables store data unique to each instance, and the __init__ method automates setting them when new objects are created. Methods like full_name encapsulate behavior so code doesn’t need to be rewritten for every employee. The self parameter is essential because Python passes the instance automatically; omitting it causes a TypeError. Calling methods on an instance vs on the class changes whether self is supplied automatically or must be passed explicitly.
What’s the practical difference between a class and an instance in Python?
Why are instance variables better than manually assigning attributes to each object?
How does __init__ change object creation?
What role does self play in class methods, and what happens if it’s omitted?
How do method calls differ when invoked on an instance vs on the class?
Why create a full_name method instead of formatting strings outside the class?
Review Questions
- When you create employee1 = Employee('Corey','Schaefer',50000), what arguments does __init__ receive, and which one is automatically supplied?
- What error occurs if a method like full_name is defined without the self parameter, and why does it happen?
- How does calling Employee.full_name(employee1) differ from calling employee1.full_name() in terms of how self is provided?
Key Points
- 1
Classes act as blueprints, while instances are the individual objects created from those blueprints.
- 2
Instance variables store data unique to each object, such as first name, last name, email, and pay for each employee.
- 3
The __init__ method runs automatically during instance creation and is the standard place to set instance variables.
- 4
Methods encapsulate behavior; full_name returns a computed value using instance data instead of duplicating formatting code.
- 5
The self parameter is required because Python automatically passes the instance to instance methods.
- 6
Calling a method on an instance supplies self automatically; calling the same method on the class requires passing the instance explicitly.