Classes and Objects in Detail
Deep Dive into Object Creation and Usage
Class Structure
python
class ClassName:
"""Class docstring"""
# Class attribute (shared by all objects)
class_variable = "shared"
def __init__(self, param1, param2):
"""Constructor"""
self.param1 = param1 # Instance attribute
self.param2 = param2
def instance_method(self):
"""Instance method"""
return self.param1
@classmethod
def class_method(cls):
"""Class method"""
return cls.class_variable
@staticmethod
def static_method():
"""Static method"""
return "Does not depend on class or instance"Instance Attributes vs Class Attributes
python
class Survey:
# Class attribute (shared by all surveys)
total_surveys = 0
def __init__(self, name, year):
# Instance attributes (unique to each survey)
self.name = name
self.year = year
Survey.total_surveys += 1 # Modify class attribute
survey1 = Survey("Income Survey", 2024)
survey2 = Survey("Health Survey", 2024)
print(survey1.name) # Income Survey (instance attribute)
print(Survey.total_surveys) # 2 (class attribute)Common Special Methods
__init__: Constructor
python
class Respondent:
def __init__(self, id, age, income):
self.id = id
self.age = age
self.income = income
print(f"Created respondent {id}")
resp = Respondent(1001, 30, 75000) # Automatically calls __init____str__: String Representation
python
class Respondent:
def __init__(self, id, age):
self.id = id
self.age = age
def __str__(self):
return f"Respondent(ID={self.id}, Age={self.age})"
resp = Respondent(1001, 30)
print(resp) # Respondent(ID=1001, Age=30)__repr__: Developer Representation
python
class Respondent:
def __init__(self, id, age):
self.id = id
self.age = age
def __repr__(self):
return f"Respondent({self.id}, {self.age})"
resp = Respondent(1001, 30)
print(repr(resp)) # Respondent(1001, 30)__len__: Length
python
class Survey:
def __init__(self, name):
self.name = name
self.responses = []
def add_response(self, response):
self.responses.append(response)
def __len__(self):
return len(self.responses)
survey = Survey("Test")
survey.add_response({'id': 1})
survey.add_response({'id': 2})
print(len(survey)) # 2Practical Cases
Case: Student Management System
python
class Student:
"""Student class"""
school_name = "Peking University" # Class attribute
def __init__(self, student_id, name, major, gpa=0.0):
self.student_id = student_id
self.name = name
self.major = major
self.gpa = gpa
self.courses = []
def enroll_course(self, course_name, credits):
"""Enroll in a course"""
self.courses.append({
'name': course_name,
'credits': credits
})
def get_total_credits(self):
"""Calculate total credits"""
return sum(c['credits'] for c in self.courses)
def update_gpa(self, new_gpa):
"""Update GPA"""
if 0 <= new_gpa <= 4.0:
self.gpa = new_gpa
else:
print("GPA must be between 0-4.0")
def __str__(self):
return f"{self.name} ({self.major}, GPA: {self.gpa})"
# Usage
alice = Student(2024001, "Alice Wang", "Economics", 3.8)
alice.enroll_course("Microeconomics", 4)
alice.enroll_course("Econometrics", 4)
print(alice)
print(f"Total credits: {alice.get_total_credits()}")
print(f"School: {Student.school_name}")Case: Survey Data Container
python
class SurveyData:
"""Survey data management class"""
def __init__(self, survey_name):
self.survey_name = survey_name
self.responses = []
def add_response(self, response):
"""Add a response"""
if self._validate(response):
self.responses.append(response)
return True
return False
def _validate(self, response):
"""Private method: validate data"""
required_fields = ['id', 'age', 'income']
return all(field in response for field in required_fields)
def get_average_income(self):
"""Calculate average income"""
if not self.responses:
return 0
incomes = [r['income'] for r in self.responses]
return sum(incomes) / len(incomes)
def filter_by_age(self, min_age, max_age):
"""Filter by age"""
return [r for r in self.responses
if min_age <= r['age'] <= max_age]
def __len__(self):
return len(self.responses)
def __str__(self):
return f"{self.survey_name}: {len(self)} responses"
# Usage
survey = SurveyData("2024 Income Survey")
survey.add_response({'id': 1, 'age': 30, 'income': 75000})
survey.add_response({'id': 2, 'age': 35, 'income': 85000})
print(survey)
print(f"Average income: ${survey.get_average_income():,.0f}")
print(f"Ages 30-40: {len(survey.filter_by_age(30, 40))} people")Property Decorator
@property: Computed Attributes
python
class Respondent:
def __init__(self, income, tax_rate=0.25):
self.income = income
self.tax_rate = tax_rate
@property
def net_income(self):
"""Access as an attribute, not a method"""
return self.income * (1 - self.tax_rate)
@property
def tax_amount(self):
return self.income * self.tax_rate
resp = Respondent(100000, 0.3)
print(resp.net_income) # 70000 (access like an attribute)
print(resp.tax_amount) # 30000
# No need for resp.net_income()Encapsulation: Public vs Private
python
class BankAccount:
def __init__(self, balance):
self.balance = balance # Public attribute
self._transactions = [] # Convention private (single underscore)
self.__pin = "1234" # True private (double underscore)
def deposit(self, amount):
"""Public method"""
self.balance += amount
self._log_transaction("deposit", amount)
def _log_transaction(self, type, amount):
"""Private method (convention)"""
self._transactions.append({
'type': type,
'amount': amount
})
account = BankAccount(1000)
account.deposit(500)
print(account.balance) # 1500 (accessible)
print(account._transactions) # Accessible but not recommended
# print(account.__pin) # AttributeErrorPractice Problems
Exercise 1: Create a Complete Class
python
# Create a Course class
# Attributes: course_code, name, instructor, max_students, enrolled
# Methods:
# - add_student(student_name): Add student (check capacity limit)
# - drop_student(student_name): Remove student
# - is_full(): Check if full
# - get_enrollment_rate(): Return enrollment rateExercise 2: Implement Special Methods
python
# For the Survey class, implement:
# - __str__: Return "Survey: {name} ({count} responses)"
# - __len__: Return number of responses
# - __getitem__: Support survey[0] to access the i-th responseNext Steps
In the next section, we'll learn about OOP applications in data science.
Keep going!