Constructor và Methods
Constructor là gì?
Phần tiêu đề “Constructor là gì?”Constructor (Hàm khởi tạo) là một phương thức đặc biệt được gọi tự động khi tạo một object mới. Trong Python, constructor là phương thức __init__().
Mục đích của Constructor:
Phần tiêu đề “Mục đích của Constructor:”- Khởi tạo giá trị ban đầu cho các thuộc tính
- Thực hiện các thiết lập cần thiết khi tạo object
- Chuẩn bị object để sử dụng
Cú pháp Constructor
Phần tiêu đề “Cú pháp Constructor”class ClassName: def __init__(self, parameters): # Khởi tạo thuộc tính self.attribute = valueVí dụ cơ bản
Phần tiêu đề “Ví dụ cơ bản”class Person: def __init__(self, name, age): self.name = name self.age = age print(f"Đã tạo object Person: {name}")
# Khi tạo object, __init__() được gọi tự độngperson1 = Person("An", 20) # Đã tạo object Person: Anperson2 = Person("Bình", 25) # Đã tạo object Person: BìnhConstructor với giá trị mặc định
Phần tiêu đề “Constructor với giá trị mặc định”class Student: def __init__(self, name, grade="10A", gpa=0.0): self.name = name self.grade = grade self.gpa = gpa
# Truyền đầy đủ tham sốs1 = Student("An", "11B", 8.5)
# Sử dụng giá trị mặc địnhs2 = Student("Bình") # grade="10A", gpa=0.0
# Truyền một số tham sốs3 = Student("Cường", gpa=7.5) # grade="10A"
print(f"{s1.name}: {s1.grade}, GPA: {s1.gpa}") # An: 11B, GPA: 8.5print(f"{s2.name}: {s2.grade}, GPA: {s2.gpa}") # Bình: 10A, GPA: 0.0print(f"{s3.name}: {s3.grade}, GPA: {s3.gpa}") # Cường: 10A, GPA: 7.5Constructor với validation (kiểm tra dữ liệu)
Phần tiêu đề “Constructor với validation (kiểm tra dữ liệu)”class BankAccount: def __init__(self, account_number, balance=0): if balance < 0: raise ValueError("Số dư không thể âm!") if len(account_number) < 6: raise ValueError("Số tài khoản phải có ít nhất 6 ký tự!")
self.account_number = account_number self.balance = balance
# Hợp lệaccount1 = BankAccount("123456", 1000000)
# Không hợp lệ - sẽ báo lỗitry: account2 = BankAccount("123", 500000) # Lỗi: số TK quá ngắnexcept ValueError as e: print(f"Lỗi: {e}")
try: account3 = BankAccount("123456", -1000) # Lỗi: số dư âmexcept ValueError as e: print(f"Lỗi: {e}")Methods (Phương thức)
Phần tiêu đề “Methods (Phương thức)”Methods là các hàm được định nghĩa bên trong class. Có 3 loại methods chính:
1. Instance Methods (Phương thức thể hiện)
Phần tiêu đề “1. Instance Methods (Phương thức thể hiện)”Phương thức thường gặp nhất, làm việc với instance (object) cụ thể.
class Circle: def __init__(self, radius): self.radius = radius
def area(self): # Instance method return 3.14159 * self.radius ** 2
def circumference(self): # Instance method return 2 * 3.14159 * self.radius
def scale(self, factor): # Instance method self.radius *= factor
circle = Circle(5)print(f"Diện tích: {circle.area()}") # 78.53975print(f"Chu vi: {circle.circumference()}") # 31.4159
circle.scale(2) # Tăng bán kính lên 2 lầnprint(f"Bán kính mới: {circle.radius}") # 102. Class Methods (Phương thức lớp)
Phần tiêu đề “2. Class Methods (Phương thức lớp)”Làm việc với class, không phải với instance cụ thể. Sử dụng decorator @classmethod.
class Employee: company = "Tech Corp" # Class attribute employee_count = 0
def __init__(self, name, salary): self.name = name self.salary = salary Employee.employee_count += 1
@classmethod def get_employee_count(cls): return cls.employee_count
@classmethod def set_company(cls, company_name): cls.company = company_name
# Tạo nhân viênemp1 = Employee("An", 10000000)emp2 = Employee("Bình", 12000000)
# Gọi class methodprint(Employee.get_employee_count()) # 2Employee.set_company("New Tech Corp")print(Employee.company) # New Tech CorpKhi nào dùng class method:
- Khi cần truy cập/thay đổi class attributes
- Tạo alternative constructors (hàm khởi tạo thay thế)
3. Static Methods (Phương thức tĩnh)
Phần tiêu đề “3. Static Methods (Phương thức tĩnh)”Không truy cập vào instance hay class. Sử dụng decorator @staticmethod.
class MathUtils: @staticmethod def add(a, b): return a + b
@staticmethod def is_even(num): return num % 2 == 0
@staticmethod def factorial(n): if n <= 1: return 1 return n * MathUtils.factorial(n - 1)
# Gọi static method không cần tạo objectprint(MathUtils.add(5, 3)) # 8print(MathUtils.is_even(10)) # Trueprint(MathUtils.factorial(5)) # 120Khi nào dùng static method:
- Hàm tiện ích không cần truy cập instance hoặc class
- Nhóm các hàm liên quan vào một class
So sánh 3 loại Methods
Phần tiêu đề “So sánh 3 loại Methods”class MyClass: class_var = "Class Variable"
def __init__(self, value): self.instance_var = value
# Instance Method def instance_method(self): return f"Instance: {self.instance_var}, Class: {self.class_var}"
# Class Method @classmethod def class_method(cls): return f"Class: {cls.class_var}"
# Static Method @staticmethod def static_method(): return "Static method - không truy cập class hay instance"
obj = MyClass("Instance Value")
print(obj.instance_method()) # Instance: Instance Value, Class: Class Variableprint(MyClass.class_method()) # Class: Class Variableprint(MyClass.static_method()) # Static method - không truy cập class hay instance| Loại Method | Tham số đầu | Truy cập instance? | Truy cập class? | Gọi từ |
|---|---|---|---|---|
| Instance | self |
✅ Có | ✅ Có | Object |
| Class | cls |
❌ Không | ✅ Có | Class/Object |
| Static | Không | ❌ Không | ❌ Không | Class/Object |
Alternative Constructor với Class Method
Phần tiêu đề “Alternative Constructor với Class Method”class Date: def __init__(self, day, month, year): self.day = day self.month = month self.year = year
@classmethod def from_string(cls, date_string): """Tạo Date từ string định dạng 'dd-mm-yyyy'""" day, month, year = map(int, date_string.split('-')) return cls(day, month, year)
@classmethod def today(cls): """Tạo Date với ngày hôm nay""" import datetime today = datetime.date.today() return cls(today.day, today.month, today.year)
def display(self): print(f"{self.day:02d}/{self.month:02d}/{self.year}")
# Cách thông thườngdate1 = Date(25, 12, 2024)date1.display() # 25/12/2024
# Dùng class methoddate2 = Date.from_string("15-08-2024")date2.display() # 15/08/2024
date3 = Date.today()date3.display() # Ngày hôm nayVí dụ thực tế: Class Product
Phần tiêu đề “Ví dụ thực tế: Class Product”class Product: # Class attribute tax_rate = 0.1 # 10% VAT
def __init__(self, name, price, quantity=0): self.name = name self.price = price self.quantity = quantity
def get_total_price(self): """Instance method: Tính tổng giá trị""" return self.price * self.quantity
def get_price_with_tax(self): """Instance method: Tính giá có thuế""" return self.price * (1 + Product.tax_rate)
def add_stock(self, amount): """Instance method: Thêm hàng vào kho""" if amount > 0: self.quantity += amount print(f"Đã thêm {amount} sản phẩm. Tồn kho: {self.quantity}")
def sell(self, amount): """Instance method: Bán hàng""" if amount > self.quantity: print("Không đủ hàng trong kho!") return False self.quantity -= amount total = amount * self.get_price_with_tax() print(f"Đã bán {amount} sản phẩm. Tổng tiền: {total:,.0f}đ") return True
@classmethod def set_tax_rate(cls, rate): """Class method: Thay đổi thuế suất cho tất cả sản phẩm""" cls.tax_rate = rate print(f"Đã đổi thuế suất thành {rate*100}%")
@staticmethod def is_valid_price(price): """Static method: Kiểm tra giá hợp lệ""" return price > 0
def __str__(self): """Special method: Hiển thị thông tin sản phẩm""" return f"{self.name} - Giá: {self.price:,}đ - Tồn kho: {self.quantity}"
# Sử dụngproduct = Product("Laptop Dell", 15000000, 10)print(product) # Laptop Dell - Giá: 15,000,000đ - Tồn kho: 10
product.add_stock(5) # Đã thêm 5 sản phẩm. Tồn kho: 15product.sell(3) # Đã bán 3 sản phẩm. Tổng tiền: 49,500,000đ
# Thay đổi thuế suất cho tất cả sản phẩmProduct.set_tax_rate(0.08) # Đã đổi thuế suất thành 8.0%
# Kiểm tra giá hợp lệprint(Product.is_valid_price(15000000)) # Trueprint(Product.is_valid_price(-100)) # FalseGetter và Setter Methods
Phần tiêu đề “Getter và Setter Methods”class Temperature: def __init__(self, celsius=0): self._celsius = celsius # Protected attribute
def get_celsius(self): """Getter method""" return self._celsius
def set_celsius(self, value): """Setter method""" if value < -273.15: raise ValueError("Nhiệt độ không thể thấp hơn -273.15°C") self._celsius = value
def get_fahrenheit(self): """Chuyển đổi sang Fahrenheit""" return self._celsius * 9/5 + 32
def set_fahrenheit(self, value): """Đặt nhiệt độ từ Fahrenheit""" celsius = (value - 32) * 5/9 self.set_celsius(celsius)
temp = Temperature(25)print(f"Celsius: {temp.get_celsius()}°C") # 25°Cprint(f"Fahrenheit: {temp.get_fahrenheit()}°F") # 77.0°F
temp.set_fahrenheit(98.6) # Đặt theo Fahrenheitprint(f"Celsius: {temp.get_celsius():.1f}°C") # 37.0°CProperty Decorator (Cách Pythonic)
Phần tiêu đề “Property Decorator (Cách Pythonic)”class Temperature: def __init__(self, celsius=0): self._celsius = celsius
@property def celsius(self): """Getter""" return self._celsius
@celsius.setter def celsius(self, value): """Setter""" if value < -273.15: raise ValueError("Nhiệt độ không thể thấp hơn -273.15°C") self._celsius = value
@property def fahrenheit(self): """Getter cho Fahrenheit""" return self._celsius * 9/5 + 32
@fahrenheit.setter def fahrenheit(self, value): """Setter cho Fahrenheit""" self.celsius = (value - 32) * 5/9
# Sử dụng như thuộc tính thông thườngtemp = Temperature(25)print(temp.celsius) # 25print(temp.fahrenheit) # 77.0
temp.celsius = 30 # Dùng setterprint(temp.fahrenheit) # 86.0
temp.fahrenheit = 32 # Dùng setterprint(temp.celsius) # 0.0Method Chaining
Phần tiêu đề “Method Chaining”class Calculator: def __init__(self): self.value = 0
def add(self, num): self.value += num return self # Trả về chính object
def subtract(self, num): self.value -= num return self
def multiply(self, num): self.value *= num return self
def divide(self, num): if num != 0: self.value /= num return self
def result(self): return self.value
# Method chainingcalc = Calculator()result = calc.add(10).multiply(5).subtract(20).divide(3).result()print(result) # 10.0# Tương đương: ((10 * 5) - 20) / 3 = 10Bài tập thực hành
Phần tiêu đề “Bài tập thực hành”Bài 1: Class ShoppingCart
Phần tiêu đề “Bài 1: Class ShoppingCart”class ShoppingCart: def __init__(self): self.items = []
def add_item(self, name, price, quantity=1): """Thêm sản phẩm vào giỏ""" self.items.append({ 'name': name, 'price': price, 'quantity': quantity }) return self
def get_total(self): """Tính tổng tiền""" return sum(item['price'] * item['quantity'] for item in self.items)
def display_cart(self): """Hiển thị giỏ hàng""" print("=== GIỎ HÀNG ===") for i, item in enumerate(self.items, 1): total = item['price'] * item['quantity'] print(f"{i}. {item['name']} x{item['quantity']} = {total:,}đ") print(f"Tổng cộng: {self.get_total():,}đ")
@staticmethod def format_currency(amount): """Format số tiền""" return f"{amount:,.0f}đ"
# Testcart = ShoppingCart()cart.add_item("Laptop", 15000000).add_item("Mouse", 200000, 2).add_item("Keyboard", 500000)cart.display_cart()Tổng kết
Phần tiêu đề “Tổng kết”__init__()là constructor, được gọi tự động khi tạo object- Instance methods làm việc với object cụ thể (tham số
self) - Class methods làm việc với class (
@classmethod, tham sốcls) - Static methods là hàm tiện ích (
@staticmethod, không cóselfhaycls) - Property decorator giúp tạo getter/setter theo cách Pythonic
- Method chaining cho phép gọi nhiều method liên tiếp
Trong bài tiếp theo, chúng ta sẽ tìm hiểu về Inheritance (Kế thừa)!