Previous | Tutorial index | Next
__init__Learn the exact Python syntax for defining a class and initializing objects.
class Keyword: Your Blueprint Starts HereIn Python, you define a new class using the class keyword, followed by the class name and a colon (:).
class Dog:
pass # 'pass' is a placeholder so the class isn't empty
BankAccount, not bank_account or Bank_Account.Customer, Order, Product, not Customers, Orders.HTMLParser is fine).pass Statementpass is a null operationâit does nothing. It is used as a placeholder when you need a block of code syntactically but don't want any logic yet. A class definition must have an indented block, even if empty.Immediately after the class header, you should include a docstring (tripleâquoted string) that describes the purpose of the class.
class Dog:
"""A simple model of a dog."""
pass
__init__() Method: The Initializer (Not a Constructor)Important distinction: In many programming languages, the method that creates an object is called a "constructor." In Python, the actual constructor is __new__(), which allocates memory for the object. The __init__() method is an initializerâit runs immediately after the object is created to set its initial state.
__init__() Do?__init__, Python still creates objects, but they will have no initial attributes until you manually assign them later (which is not recommended).class ClassName:
def __init__(self, parameter1, parameter2, ...):
self.attribute1 = parameter1
self.attribute2 = parameter2
__init__ (two underscores on each side).self (more on this below).self Parameter: The Instance's Own Identityself is a reference to the current instance of the class. When you create an object, Python passes that object itself as the first argument to the method.
self?self.name = name, you are saying: "Store this name value inside this specific object's memory space."this, me, instance), but always use self. It is a universal convention in the Python community, and every Python developer expects it. Using anything else is considered bad practice and makes your code confusing.self AutomaticallyWhen you call my_dog = Dog("Fido", 3), Python internally does something like this:
__init__ and passes the new object as the self argument, along with "Fido" and 3.__init__ method uses self to attach attributes to that specific object.Critical: When you call an instance method later (like my_dog.speak()), Python automatically passes my_dog as self. You never need to pass self manually when calling a methodâPython handles it for you.
Inside __init__, you define instance attributesâdata that belongs to each individual object.
class Dog:
def __init__(self, name, age):
self.name = name # Instance attribute
self.age = age # Instance attribute
self. to indicate it belongs to the instance.You can also set default values for attributes, making them optional during instantiation.
class Dog:
def __init__(self, name, age=0, breed="Unknown"):
self.name = name
self.age = age # Age defaults to 0 if not provided
self.breed = breed # Breed defaults to "Unknown"
Now you can create a dog with just a name: Dog("Fido") â age is 0, breed is "Unknown".
You can define attributes that are not passed as parameters. These are useful for state that starts with a fixed default.
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
self.current_page = 1 # Not passed in; always starts at 1
self.is_open = False # Not passed in; always starts closed
An instance method is a function defined inside a class that operates on an instance of that class.
self (the instance the method is being called on).self.attribute.Dog Classclass Dog:
def __init__(self, name, age, breed="Unknown"):
self.name = name
self.age = age
self.breed = breed
self.energy = 100
# Instance method that reads state
def speak(self):
return f"{self.name} says woof!"
# Instance method that modifies state
def play(self, minutes):
self.energy -= minutes * 2
if self.energy < 0:
self.energy = 0
return f"{self.name} played for {minutes} minutes. Energy is now {self.energy}."
# Instance method that uses parameters
def birthday(self):
self.age += 1
return f"Happy birthday, {self.name}! You are now {self.age} years old."
self), so you don't need to pass the object's data in as arguments.dog.play(30) is much clearer than play(dog, 30).Student ClassLet's build a complete class from scratch to solidify the concepts.
class Student:
"""A simple model of a university student."""
def __init__(self, name, student_id, major):
"""Initialize the student with required information."""
self.name = name
self.student_id = student_id
self.major = major
self.gpa = 0.0 # Default GPA for new students
self.courses = [] # Empty list to store enrolled courses
def enroll(self, course_name):
"""Enroll the student in a course."""
if course_name not in self.courses:
self.courses.append(course_name)
return f"{self.name} enrolled in {course_name}"
else:
return f"{self.name} is already enrolled in {course_name}"
def update_gpa(self, new_gpa):
"""Update the student's GPA with validation."""
if 0.0 <= new_gpa <= 4.0:
self.gpa = new_gpa
return f"GPA updated to {self.gpa}"
else:
raise ValueError("GPA must be between 0.0 and 4.0")
def display_info(self):
"""Return a formatted summary of the student."""
courses_str = ", ".join(self.courses) if self.courses else "No courses"
return (f"Student: {self.name} (ID: {self.student_id})\n"
f"Major: {self.major}\n"
f"GPA: {self.gpa}\n"
f"Courses: {courses_str}")
# --- Creating and using objects ---
alice = Student("Alice Johnson", "S001", "Computer Science")
bob = Student("Bob Smith", "S002", "Engineering")
# Calling methods
print(alice.enroll("CS101")) # Alice Johnson enrolled in CS101
print(alice.enroll("CS101")) # Alice Johnson is already enrolled in CS101
print(alice.enroll("MATH201")) # Alice Johnson enrolled in MATH201
alice.update_gpa(3.8)
print(alice.display_info())
print(bob.display_info()) # Bob has no courses and GPA 0.0
Output (for alice.display_info()):
Student: Alice Johnson (ID: S001)
Major: Computer Science
GPA: 3.8
Courses: CS101, MATH201
Notice that alice and bob are completely independentâchanging Alice's GPA or courses does not affect Bob.
| Pitfall | Explanation | How to Avoid |
|---|---|---|
Forgetting self as the first parameter |
def speak(): (no self). When you call dog.speak(), Python tries to pass dog as an argument but the method doesn't accept it â TypeError: speak() takes 0 positional arguments but 1 was given. |
Always include self as the first parameter for all instance methods and __init__. |
| Forgetting to assign an attribute | If you write self.name = name but forget self.age = age, then dog.age will raise an AttributeError. |
Always assign every attribute you intend to use. Doubleâcheck your __init__ body. |
Using a mutable default value in __init__ |
def __init__(self, items=[]): - This creates a shared list across all instances, leading to subtle bugs. |
Use def __init__(self, items=None): and then self.items = items if items is not None else []. |
| Accessing a method incorrectly | Writing dog.speak (without parentheses) returns the method object itself, not the result. |
Always add parentheses when you want to call the method: dog.speak(). |
Confusing __init__ with a constructor |
Thinking __init__ creates the object. It doesn'tâit initializes it. |
For this unit, you don't need __new__. Just know that __init__ is for setting initial state. |
Using self outside a method |
Writing self.name = "Fido" at the top level of a class (outside any method) is invalid. |
Only use self inside instance methods (including __init__). |
__init__Answer the following questions to check your understanding.
1. What is the correct way to define a class in Python?
class MyClassclass MyClass():class MyClass:Class MyClass:2. The __init__ method in Python is best described as:
3. What does the self parameter represent in an instance method?
4. Consider the following code:
class Car:
def __init__(self, model):
self.model = model
What is model in the parameter list?
self.model.5. Which of the following will correctly create an instance of the Book class?
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
my_book = Book()my_book = Book("1984", "Orwell")my_book = Book(title="1984", author="Orwell")6. (True/False) You can name the first parameter of an instance method anything you like (e.g., this), but self is the convention.
7. What will be the output of the following code?
class Cat:
def __init__(self, name):
self.name = name
def meow(self):
return self.name + " says meow!"
kitty = Cat("Fluffy")
print(kitty.meow)
Fluffy says meow!<bound method Cat.meow of <__main__.Cat object at ...>>Fluffy says meow! is printed but with an error.None8. How do you make an attribute optional (with a default value) in __init__?
def __init__(self, name, age=0):def __init__(self, name, age optional=0):def __init__(self, name, age = default 0):def __init__(self, name, age): self.age = age or 0Part A: Build a Product Class
Create a class called Product with the following requirements:
__init__): name (str), price (float), quantity (int, default 0).total_value(): Returns the total value of the stock (price Ă quantity).sell(amount): Reduces the quantity by amount. If amount exceeds current quantity, raise a ValueError with a clear message. Otherwise, return the new quantity.restock(amount): Increases the quantity by amount and returns the new quantity.display(): Returns a string like "Product: Laptop | Price: $999.99 | Quantity: 5".Part B: Instantiate and Test
Create three product objects (e.g., a laptop, a mouse, and a monitor). Perform the following operations:
try/except block.Part C: Reflection Question
In a comment in your code, answer: "Why does self allow the sell() method to work correctly for each product without us having to pass the product's quantity as a separate argument?"
Task: You are building a simplified banking system. Write a complete Python script that defines a BankAccount class with the following rigorous specifications.
Attributes (set in __init__):
account_holder (str) â name of the owner.account_number (int) â a unique number (passed in).balance (float) â starting balance, default 0.0.interest_rate (float) â annual interest rate as a decimal (e.g., 0.02 for 2%), default 0.01.transaction_history (list) â an empty list to store strings describing each transaction.Instance Methods:
deposit(amount): Adds amount to the balance. If amount is negative or zero, raise a ValueError. Add a transaction record like "Deposited $100.00". Return the new balance.
withdraw(amount): Subtracts amount from the balance. If amount is negative or greater than the current balance, raise a ValueError. Add a transaction record like "Withdrew $50.00". Return the new balance.
apply_interest(): Multiplies the current balance by (1 + interest_rate) and adds a transaction record "Applied interest at X%". Return the new balance.
get_balance(): Returns the current balance.
get_transaction_history(): Returns the list of transaction strings.
display_summary(): Returns a formatted string like:
Account: 12345
Holder: Alice Johnson
Balance: $1,250.75
Interest Rate: 2.0%
Transactions: 3
Part 1: Code
Write the full class definition with all methods. Make sure to include:
ValueError for invalid operations).Part 2: Testing Script
In the same file, create a main() function (or topâlevel code) that does the following:
Part 3: Written Reflection
Answer these questions in a comment block at the top of your script:
deposit() method if we forgot to include self as the first parameter? (Be specific about the error that would occur.)transaction_history list is defined inside __init__ rather than as a global list outside the class? (Hint: think about encapsulation and data integrity.)balance (e.g., preventing account.balance = 99999), how could we use encapsulation to enforce that all changes go through deposit() and withdraw()? (You don't need to code itâjust explain the concept.)If you want to deepen your understanding, explore these materials:
Before moving to Tutorial 3 (Creating and Using Objects), ensure you can confidently say YES to the following:
Ready for the next tutorial? In Tutorial 3, you will dive deeper into creating multiple objects, accessing their attributes, and calling their methods in practical scenarios.