Classes and Methods: Python Basics
This content contains beginner-friendly Python code examples focused on understanding classes and instance methods. These examples demonstrate how Python organizes code into classes and objects, showing the fundamental building blocks of object-oriented programming in Python.
How to Read These Examples
- Start with the class definition - Understand what data the object will hold
- Follow the
__init__
method - See how objects are created and initialized - Trace method calls - Follow how methods access and modify object attributes
- Notice the
self
parameter - See how methods reference the current object - Practice Pythonic thinking - Understand Python’s approach to object-oriented programming
Example 1: Simple Student Class with Basic Methods
Code to Read:
1class Student:
2 """A simple class to represent a student"""
3
4 def __init__(self, name, age, grade):
5 """Initialize a new student object"""
6 self.name = name # Instance attribute
7 self.age = age
8 self.grade = grade
9 self.courses = [] # Start with empty course list
10 self.is_enrolled = True
11
12 def get_name(self):
13 """Return the student's name"""
14 return self.name
15
16 def get_age(self):
17 """Return the student's age"""
18 return self.age
19
20 def get_grade(self):
21 """Return the student's grade level"""
22 return self.grade
23
24 def is_student_enrolled(self):
25 """Check if student is currently enrolled"""
26 return self.is_enrolled
27
28 def add_course(self, course_name):
29 """Add a course to the student's schedule"""
30 if course_name not in self.courses:
31 self.courses.append(course_name)
32 print(f"Added {course_name} to {self.name}'s schedule")
33 else:
34 print(f"{self.name} is already enrolled in {course_name}")
35
36 def drop_course(self, course_name):
37 """Remove a course from the student's schedule"""
38 if course_name in self.courses:
39 self.courses.remove(course_name)
40 print(f"Dropped {course_name} from {self.name}'s schedule")
41 else:
42 print(f"{self.name} is not enrolled in {course_name}")
43
44 def get_courses(self):
45 """Return a copy of the student's course list"""
46 return self.courses.copy()
47
48 def get_course_count(self):
49 """Return the number of courses the student is taking"""
50 return len(self.courses)
51
52 def withdraw(self):
53 """Withdraw the student from school"""
54 self.is_enrolled = False
55 self.courses = [] # Clear all courses
56 print(f"{self.name} has withdrawn from school")
57
58 def re_enroll(self):
59 """Re-enroll the student"""
60 self.is_enrolled = True
61 print(f"{self.name} has re-enrolled in school")
62
63 def get_info(self):
64 """Return formatted information about the student"""
65 status = "Enrolled" if self.is_enrolled else "Withdrawn"
66 course_list = ", ".join(self.courses) if self.courses else "None"
67 return f"{self.name} (Age: {self.age}, Grade: {self.grade}, Status: {status}, Courses: {course_list})"
68
69# Using the Student class
70def demo_student_class():
71 """Demonstrate how to use the Student class"""
72
73 # Create student objects
74 alice = Student("Alice Johnson", 16, 10)
75 bob = Student("Bob Smith", 17, 11)
76
77 # Use methods to access information
78 print("=== Student Information ===")
79 print(f"Student name: {alice.get_name()}")
80 print(f"Alice's age: {alice.get_age()}")
81 print(f"Bob's grade: {bob.get_grade()}")
82 print()
83
84 # Add courses
85 print("=== Adding Courses ===")
86 alice.add_course("Math")
87 alice.add_course("English")
88 alice.add_course("Science")
89 bob.add_course("History")
90 bob.add_course("Math")
91 print()
92
93 # Display course information
94 print("=== Course Information ===")
95 print(f"Alice's courses: {alice.get_courses()}")
96 print(f"Alice is taking {alice.get_course_count()} courses")
97 print(f"Bob's courses: {bob.get_courses()}")
98 print()
99
100 # Modify student status
101 print("=== Status Changes ===")
102 alice.drop_course("Science")
103 bob.withdraw()
104 print()
105
106 # Show final information
107 print("=== Final Student Info ===")
108 print(alice.get_info())
109 print(bob.get_info())
110
111# Run the demo
112if __name__ == "__main__":
113 demo_student_class()
What to Notice:
Details
- Class keyword:
class Student:
defines a new class __init__
method: Special method that runs when creating new objectsself
parameter: Always the first parameter in instance methods - refers to the current object- Instance attributes:
self.name
,self.age
store data specific to each object - Default values:
self.courses = []
sets up initial state
Details
self
in every method: All instance methods must haveself
as first parameter- Accessing attributes:
self.name
refers to the current object’s name attribute - Method naming: Python uses
snake_case
for method names (unlike Java’s camelCase) - Return values: Methods can return data or modify object state
- No explicit typing: Python doesn’t require type declarations
Details
- Separate objects:
alice
andbob
are independent Student objects - Individual attributes: Each object has its own
name
,age
,courses
list - State changes: Methods modify the specific object they’re called on
- List attributes: Each object gets its own separate
courses
list
Trace Through Example:
1# Object creation:
2alice = Student("Alice Johnson", 16, 10)
3# 1. Python calls Student.__init__(alice, "Alice Johnson", 16, 10)
4# 2. alice.name = "Alice Johnson"
5# 3. alice.age = 16
6# 4. alice.grade = 10
7# 5. alice.courses = []
8# 6. alice.is_enrolled = True
9
10# Method calls:
11alice.get_name() # → returns "Alice Johnson"
12alice.add_course("Math")
13# 1. Check if "Math" not in alice.courses → True
14# 2. alice.courses.append("Math") → courses becomes ["Math"]
15# 3. Print confirmation message
16
17alice.get_course_count() # → returns len(alice.courses) → 1
Example 2: Simple Calculator Class with Mathematical Operations
Code to Read:
1class Calculator:
2 """A simple calculator that remembers its result"""
3
4 def __init__(self):
5 """Initialize calculator with zero result"""
6 self.result = 0.0
7 self.history = [] # Keep track of operations
8
9 def get_result(self):
10 """Return the current result"""
11 return self.result
12
13 def get_history(self):
14 """Return a copy of the operation history"""
15 return self.history.copy()
16
17 def clear(self):
18 """Reset calculator to zero"""
19 self.result = 0.0
20 self.history.append("CLEAR")
21 print("Calculator cleared")
22
23 def add(self, number):
24 """Add a number to the current result"""
25 self.result += number
26 operation = f"{self.result - number} + {number} = {self.result}"
27 self.history.append(operation)
28 print(operation)
29 return self.result
30
31 def subtract(self, number):
32 """Subtract a number from the current result"""
33 old_result = self.result
34 self.result -= number
35 operation = f"{old_result} - {number} = {self.result}"
36 self.history.append(operation)
37 print(operation)
38 return self.result
39
40 def multiply(self, number):
41 """Multiply the current result by a number"""
42 old_result = self.result
43 self.result *= number
44 operation = f"{old_result} × {number} = {self.result}"
45 self.history.append(operation)
46 print(operation)
47 return self.result
48
49 def divide(self, number):
50 """Divide the current result by a number"""
51 if number == 0:
52 print("Error: Cannot divide by zero!")
53 return self.result
54
55 old_result = self.result
56 self.result /= number
57 operation = f"{old_result} ÷ {number} = {self.result}"
58 self.history.append(operation)
59 print(operation)
60 return self.result
61
62 def set_value(self, number):
63 """Set the calculator to a specific value"""
64 self.result = number
65 operation = f"SET {number}"
66 self.history.append(operation)
67 print(f"Calculator set to {number}")
68 return self.result
69
70 def square(self):
71 """Square the current result"""
72 old_result = self.result
73 self.result = self.result ** 2
74 operation = f"{old_result}² = {self.result}"
75 self.history.append(operation)
76 print(operation)
77 return self.result
78
79 def sqrt(self):
80 """Take the square root of the current result"""
81 if self.result < 0:
82 print("Error: Cannot take square root of negative number!")
83 return self.result
84
85 old_result = self.result
86 self.result = self.result ** 0.5
87 operation = f"√{old_result} = {self.result}"
88 self.history.append(operation)
89 print(operation)
90 return self.result
91
92# Using the Calculator class
93def demo_calculator():
94 """Demonstrate calculator functionality"""
95
96 # Create calculator objects
97 calc1 = Calculator()
98 calc2 = Calculator()
99
100 print("=== Calculator 1 ===")
101 calc1.set_value(10)
102 calc1.add(5)
103 calc1.multiply(3)
104 calc1.subtract(20)
105 print(f"Final result: {calc1.get_result()}")
106 print()
107
108 print("=== Calculator 2 ===")
109 calc2.set_value(16)
110 calc2.sqrt()
111 calc2.square()
112 calc2.divide(4)
113 print(f"Final result: {calc2.get_result()}")
114 print()
115
116 # Show operation history
117 print("=== Operation History ===")
118 print("Calculator 1 history:")
119 for operation in calc1.get_history():
120 print(f" {operation}")
121
122 print("Calculator 2 history:")
123 for operation in calc2.get_history():
124 print(f" {operation}")
125
126 # Demonstrate error handling
127 print("\n=== Error Handling ===")
128 calc1.divide(0) # Should show error message
129 calc1.clear()
130 calc1.subtract(5)
131 calc1.sqrt() # Should show error for negative number
132
133# Run the demo
134if __name__ == "__main__":
135 demo_calculator()
What to Notice:
Details
- Persistent state: Calculator remembers its
result
between operations - History tracking:
self.history
list accumulates all operations - State validation: Methods check for invalid operations (divide by zero)
- Independent calculators: Each Calculator object has its own result and history
Details
- Returning results: Most methods return
self.result
for convenience - Method chaining potential: Returned values could be used for chaining operations
- Side effects: Methods both modify state and provide user feedback
- Error handling: Methods handle edge cases and continue operation
Details
- List methods: Using
.append()
to add to history - String formatting: Using f-strings for operation descriptions
- Exponentiation: Using
**
operator for squares and square roots - Copy method:
self.history.copy()
prevents external modification
Example 3: Library Book Class with Status Tracking
Code to Read:
1class LibraryBook:
2 """A class to represent a book in a library system"""
3
4 def __init__(self, title, author, isbn):
5 """Initialize a new library book"""
6 self.title = title
7 self.author = author
8 self.isbn = isbn
9 self.is_available = True
10 self.borrowed_by = None
11 self.borrow_count = 0
12 self.borrow_history = []
13
14 def get_title(self):
15 """Return the book's title"""
16 return self.title
17
18 def get_author(self):
19 """Return the book's author"""
20 return self.author
21
22 def get_isbn(self):
23 """Return the book's ISBN"""
24 return self.isbn
25
26 def is_book_available(self):
27 """Check if the book is available for borrowing"""
28 return self.is_available
29
30 def get_borrowed_by(self):
31 """Return who currently has the book borrowed"""
32 return self.borrowed_by
33
34 def get_borrow_count(self):
35 """Return how many times the book has been borrowed"""
36 return self.borrow_count
37
38 def borrow_book(self, borrower_name):
39 """Allow someone to borrow the book"""
40 if not self.is_available:
41 print(f"Sorry, '{self.title}' is already borrowed by {self.borrowed_by}")
42 return False
43
44 self.is_available = False
45 self.borrowed_by = borrower_name
46 self.borrow_count += 1
47 self.borrow_history.append(f"Borrowed by {borrower_name}")
48 print(f"'{self.title}' has been borrowed by {borrower_name}")
49 return True
50
51 def return_book(self):
52 """Return the book to the library"""
53 if self.is_available:
54 print(f"'{self.title}' is already available in the library")
55 return False
56
57 returner = self.borrowed_by
58 self.is_available = True
59 self.borrowed_by = None
60 self.borrow_history.append(f"Returned by {returner}")
61 print(f"'{self.title}' has been returned by {returner}")
62 return True
63
64 def get_popularity_level(self):
65 """Determine how popular the book is based on borrow count"""
66 if self.borrow_count == 0:
67 return "New/Unread"
68 elif self.borrow_count <= 3:
69 return "Low popularity"
70 elif self.borrow_count <= 10:
71 return "Moderate popularity"
72 elif self.borrow_count <= 20:
73 return "Popular"
74 else:
75 return "Very popular"
76
77 def get_book_status(self):
78 """Return a detailed status of the book"""
79 availability = "Available" if self.is_available else f"Borrowed by {self.borrowed_by}"
80 return f"'{self.title}' by {self.author} - {availability} (Borrowed {self.borrow_count} times)"
81
82 def get_borrow_history(self):
83 """Return the complete borrowing history"""
84 return self.borrow_history.copy()
85
86# Using the LibraryBook class
87def demo_library_system():
88 """Demonstrate library book management"""
89
90 # Create book objects
91 book1 = LibraryBook("The Great Gatsby", "F. Scott Fitzgerald", "978-0-7432-7356-5")
92 book2 = LibraryBook("To Kill a Mockingbird", "Harper Lee", "978-0-06-112008-4")
93 book3 = LibraryBook("1984", "George Orwell", "978-0-452-28423-4")
94
95 print("=== Library System Demo ===")
96 print("Initial book status:")
97 print(book1.get_book_status())
98 print(book2.get_book_status())
99 print(book3.get_book_status())
100 print()
101
102 # Simulate borrowing
103 print("=== Borrowing Books ===")
104 book1.borrow_book("Alice Johnson")
105 book2.borrow_book("Bob Smith")
106 book1.borrow_book("Carol Davis") # Should fail - already borrowed
107 print()
108
109 # Check current status
110 print("=== Current Status ===")
111 print(book1.get_book_status())
112 print(book2.get_book_status())
113 print(book3.get_book_status())
114 print()
115
116 # Return books and borrow again
117 print("=== Returns and New Borrowing ===")
118 book1.return_book()
119 book1.borrow_book("David Wilson")
120 book1.return_book()
121 book1.borrow_book("Eve Adams")
122 print()
123
124 # Show popularity and history
125 print("=== Book Analytics ===")
126 print(f"Book 1 popularity: {book1.get_popularity_level()}")
127 print(f"Book 2 popularity: {book2.get_popularity_level()}")
128 print(f"Book 3 popularity: {book3.get_popularity_level()}")
129 print()
130
131 print("Book 1 borrowing history:")
132 for entry in book1.get_borrow_history():
133 print(f" {entry}")
134
135# Run the demo
136if __name__ == "__main__":
137 demo_library_system()
What to Notice:
Details
- Multiple related attributes:
is_available
,borrowed_by
,borrow_count
work together - State consistency: Methods ensure logical consistency between attributes
- History tracking:
borrow_history
maintains a record of all transactions - Business logic: Methods enforce library rules (can’t borrow if already borrowed)
Details
- Precondition checking: Methods verify state before performing actions
- Return values: Boolean returns indicate success/failure of operations
- User feedback: Print statements provide immediate feedback
- Graceful failure: Invalid operations don’t crash, they report errors
Details
- Derived information:
get_popularity_level()
calculates fromborrow_count
- Status reporting:
get_book_status()
combines multiple attributes - Data protection:
get_borrow_history().copy()
prevents external changes - Business intelligence: Methods provide insights into book usage patterns
Reading Practice Tips
After studying these Python class examples:
- Follow object creation: Trace how
__init__
sets up initial object state - Understand
self
: Notice howself
refers to the current object in every method - Track attribute changes: Follow how methods modify object attributes over time
- Compare objects: See how multiple instances maintain independent state
- Practice method tracing: Follow the flow of method calls and return values
These Python patterns show how object-oriented programming works in Python’s dynamic, readable style. Understanding classes and methods will help you read more complex Python code with confidence.