Skip to Content
Python🎯 Python OOPConstructor và Methods

Constructor và Methods

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:

  • 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

class ClassName: def __init__(self, parameters): # Khởi tạo thuộc tính self.attribute = value

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ự động person1 = Person("An", 20) # Đã tạo object Person: An person2 = Person("Bình", 25) # Đã tạo object Person: Bình

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 định s2 = 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.5 print(f"{s2.name}: {s2.grade}, GPA: {s2.gpa}") # Bình: 10A, GPA: 0.0 print(f"{s3.name}: {s3.grade}, GPA: {s3.gpa}") # Cường: 10A, GPA: 7.5

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ỗi try: account2 = BankAccount("123", 500000) # Lỗi: số TK quá ngắn except ValueError as e: print(f"Lỗi: {e}") try: account3 = BankAccount("123456", -1000) # Lỗi: số dư âm except ValueError as e: print(f"Lỗi: {e}")

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ươ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.53975 print(f"Chu vi: {circle.circumference()}") # 31.4159 circle.scale(2) # Tăng bán kính lên 2 lần print(f"Bán kính mới: {circle.radius}") # 10

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ên emp1 = Employee("An", 10000000) emp2 = Employee("Bình", 12000000) # Gọi class method print(Employee.get_employee_count()) # 2 Employee.set_company("New Tech Corp") print(Employee.company) # New Tech Corp

Khi 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)

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 object print(MathUtils.add(5, 3)) # 8 print(MathUtils.is_even(10)) # True print(MathUtils.factorial(5)) # 120

Khi 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

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 Variable print(MyClass.class_method()) # Class: Class Variable print(MyClass.static_method()) # Static method - không truy cập class hay instance
Loại MethodTham số đầuTruy cập instance?Truy cập class?Gọi từ
Instanceself✅ Có✅ CóObject
Classcls❌ Không✅ CóClass/Object
StaticKhông❌ Không❌ KhôngClass/Object

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ường date1 = Date(25, 12, 2024) date1.display() # 25/12/2024 # Dùng class method date2 = Date.from_string("15-08-2024") date2.display() # 15/08/2024 date3 = Date.today() date3.display() # Ngày hôm nay

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ụng product = 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: 15 product.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ẩm Product.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)) # True print(Product.is_valid_price(-100)) # False

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°C print(f"Fahrenheit: {temp.get_fahrenheit()}°F") # 77.0°F temp.set_fahrenheit(98.6) # Đặt theo Fahrenheit print(f"Celsius: {temp.get_celsius():.1f}°C") # 37.0°C

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ường temp = Temperature(25) print(temp.celsius) # 25 print(temp.fahrenheit) # 77.0 temp.celsius = 30 # Dùng setter print(temp.fahrenheit) # 86.0 temp.fahrenheit = 32 # Dùng setter print(temp.celsius) # 0.0

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 chaining calc = Calculator() result = calc.add(10).multiply(5).subtract(20).divide(3).result() print(result) # 10.0 # Tương đương: ((10 * 5) - 20) / 3 = 10

Bài tập thực hành

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}đ" # Test cart = ShoppingCart() cart.add_item("Laptop", 15000000).add_item("Mouse", 200000, 2).add_item("Keyboard", 500000) cart.display_cart()

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ó self hay cls)
  • 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)!

Last updated on