Decorator lớp
Thuộc phần Lập trình hướng đối tượng trong hành trình Python của Coddy. Bài học 40 trên 64.
Decorator lớp cho phép bạn sửa đổi hoặc bổ sung chức năng cho lớp bằng cách bọc lớp bằng một hàm khác. Chúng hoạt động giống decorator hàm nhưng áp dụng cho toàn bộ lớp.
Đây là một lớp đơn giản không có trang trí:
class Person:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, my name is {self.name}"Tạo một decorator cho lớp để thêm một phương thức mới:
def add_farewell(cls):
def farewell(self):
return f"Goodbye from {self.name}"
cls.farewell = farewell # Thêm phương thức vào lớp
return clsÁp dụng decorator cho một lớp bằng @:
@add_farewell
class EnhancedPerson:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, my name is {self.name}"Bây giờ, lớp có cả phương thức ban đầu lẫn phương thức được thêm vào:
person = EnhancedPerson("Alice")
print(person.greet()) # Xin chào, mình tên là Alice
print(person.farewell()) # Alice chào tạm biệtBạn cũng có thể bọc một phương thức có sẵn: lưu phương thức gốc để bạn vẫn có thể gọi nó bên trong hàm bọc. Cách này hữu ích khi bạn muốn thêm hành vi (như theo dõi hoặc ghi nhật ký) xung quanh một phương thức mà lớp đã có:
def add_tracking(cls):
original_greet = cls.greet # Lưu phương thức ban đầu
def tracked_greet(self):
print(f"greet was called") # Thực hiện thêm thao tác trước đó
return original_greet(self) # Gọi phương thức ban đầu
cls.greet = tracked_greet # Thay thế phương thức trong lớp
return cls
@add_tracking
class TrackedPerson:
def __init__(self, name):
self.name = name
def greet(self):
return f"Hello, my name is {self.name}"Khi bạn gọi greet lúc này, hàm bao chạy trước, rồi chuyển tiếp đến hàm gốc:
person = TrackedPerson("Alice")
print(person.greet())
# Đã gọi greet
# Xin chào, mình tên là AliceCác bước chính để bọc một phương thức hiện có là:
1. Lưu phương thức gốc: original = cls.method
2. Định nghĩa một hàm mới gọi original(self) cùng với mọi logic bổ sung.
3. Gán hàm mới trở lại lớp: cls.method = new_function
4. Trả về lớp đã sửa đổi.
Điểm chính: Decorator lớp nhận một lớp làm đầu vào, sửa đổi hoặc bổ sung chức năng cho lớp đó, rồi trả về lớp đã sửa đổi. Chúng có thể thêm phương thức, sửa đổi thuộc tính hoặc bọc chức năng hiện có. Đặt @decorator_name phía trên phần định nghĩa lớp để áp dụng chúng. Đây là cách gọn gàng để mở rộng chức năng của lớp mà không cần kế thừa.
Thử thách
Trung bìnhTrong thử thách này, bạn sẽ triển khai một trình trang trí lớp để theo dõi số lần gọi phương thức.
decorator.py- Triển khai trình trang trí lớpadd_countercalculator.py- Chứa các lớp sẽ sử dụng trình trang trí của bạn
Tệp driver.py chứa nhiều tình huống kiểm thử để xác thực phần triển khai của bạn với nhiều trường hợp sử dụng, kiểu kế thừa và trường hợp biên. Bạn không cần sửa tệp này, nhưng xem qua tệp sẽ giúp bạn hiểu hành vi mong đợi.
Tự làm thử
from calculator import Calculator
# Xử lý toàn diện các test case
test_case = input()
if test_case == "basic_functionality":
calc = Calculator()
print(calc.add(5, 3)) # Cần in ra 8
print(calc.add(2, 7)) # Cần in ra 9
print(calc.subtract(10, 4)) # Cần in ra 6
print(calc.call_counts) # Cần in ra {'add': 2, 'subtract': 1}
elif test_case == "multiple_instances":
calc1 = Calculator()
calc2 = Calculator()
print(calc1.add(5, 3)) # Cần in ra 8
print(calc2.add(2, 7)) # Cần in ra 9
print(calc1.subtract(10, 4)) # Cần in ra 6
# Cả hai instance cần dùng chung call_counts
print(calc1.call_counts) # Cần in ra {'add': 2, 'subtract': 1}
print(calc2.call_counts) # Cần in ra {'add': 2, 'subtract': 1}
print(calc1.call_counts is calc2.call_counts) # Cần in ra True
elif test_case == "method_call_order":
calc = Calculator()
print(calc.add(1, 2)) # Cần in ra 3
print(calc.subtract(5, 2)) # Cần in ra 3
print(calc.add(10, 20)) # Cần in ra 30
print(calc.add(7, 3)) # Cần in ra 10
print(calc.call_counts) # Cần in ra {'add': 3, 'subtract': 1}
elif test_case == "large_values":
calc = Calculator()
print(calc.add(1000000, 2000000)) # Cần in ra 3000000
print(calc.subtract(5000000, 2000000)) # Cần in ra 3000000
print(calc.call_counts) # Cần in ra {'add': 1, 'subtract': 1}
elif test_case == "negative_values":
calc = Calculator()
print(calc.add(-5, -3)) # Cần in ra -8
print(calc.subtract(-10, -4)) # Sẽ in ra -6
print(calc.call_counts) # Cần in ra {'add': 1, 'subtract': 1}
elif test_case == "float_values":
calc = Calculator()
print(calc.add(5.5, 3.2)) # Sẽ in ra 8.7
print(calc.subtract(10.5, 4.2)) # Sẽ in ra 6.3
print(calc.call_counts) # Cần in ra {'add': 1, 'subtract': 1}
elif test_case == "zero_values":
calc = Calculator()
print(calc.add(0, 0)) # Sẽ in ra 0
print(calc.subtract(0, 0)) # Sẽ in ra 0
print(calc.call_counts) # Cần in ra {'add': 1, 'subtract': 1}
elif test_case == "counter_reset":
calc = Calculator()
print(calc.add(5, 3)) # Cần in ra 8
print(calc.call_counts) # Cần in ra {'add': 1, 'subtract': 0}
# Đặt lại bộ đếm
calc.call_counts = {"add": 0, "subtract": 0}
print(calc.add(2, 7)) # Cần in ra 9
print(calc.call_counts) # Cần in ra {'add': 0, 'subtract': 0}
elif test_case == "counter_manipulation":
calc = Calculator()
print(calc.add(5, 3)) # Cần in ra 8
print(calc.call_counts) # Cần in ra {'add': 1, 'subtract': 0}
# Thay đổi trực tiếp bộ đếm
calc.call_counts["add"] = 100
print(calc.add(2, 7)) # Cần in ra 9
print(calc.call_counts) # Cần in ra {'add': 101, 'subtract': 0}
elif test_case == "performance_test":
calc = Calculator()
# Thực hiện 1000 phép cộng
for i in range(1000):
calc.add(i, i+1)
# Thực hiện 500 phép trừ
for i in range(500):
calc.subtract(i+10, i)
print(calc.call_counts) # Cần in ra {'add': 1000, 'subtract': 500}Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTham số selfPhương thứcThuộc tínhPhương thức khởi tạo (__init__)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnHàm super()Ghi đè phương thứcKế thừa đa lớpThứ tự phân giải phương thứcÔn tập: hệ thống phân cấp nhân viên2Decorator
Giới thiệu về decoratorDecorator thuộc tínhDecorator phương thức tĩnhDecorator phương thức lớp5Tính đa hình
Xem lại cách ghi đè phương thứcKiểu gõ vịtLớp và phương thức trừu tượngThiết kế giao diệnÔn tập: máy tính hình học8Các khái niệm OOP nâng cao
Kết hợp và kế thừaMixinPhương thức tĩnh và phương thức lớpDecorator lớpTrình quản lý ngữ cảnhTự luyện tập: Trình biên dịch Python online