6.1 Decorators cho phương thức của class
Decorators cũng có thể được sử dụng cho phương thức của class. Quan trọng là bạn cần nhớ truyền đúng các tham số self hoặc cls cho phương thức.
Chúng ta chưa đi sâu vào chi tiết về cách hoạt động của các class, nhưng mình muốn các bạn biết rằng decorators có khả năng này.
def log_method_call(func):
def wrapper(self, *args, **kwargs):
print(f"Gọi phương thức {func.__name__}")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def say_hello(self):
print("Hello from MyClass!")
obj = MyClass()
obj.say_hello()
Giải thích
Decorator (log_method_call): Decorator này nhận phương thức func và trả về một hàm mới wrapper in ra thông điệp trước khi gọi phương thức.
Phương thức class với decorator (say_hello): Phương thức say_hello được bao bọc bởi decorator log_method_call, thêm hành vi bổ sung khi nó được gọi.
Output:
Gọi phương thức say_hello
Hello from MyClass!
6.2 Nhiều Decorators
Bạn có thể sử dụng nhiều decorators cho một hàm, theo kiểu chồng lên nhau. Decorators được áp dụng theo thứ tự ngược với thứ tự khai báo của chúng.
def decorator1(func):
def wrapper():
print("Decorator 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Decorator 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
Giải thích
Decorators (decorator1 và decorator2): Các decorator này thêm thông điệp của chúng trước khi gọi hàm func.
Hàm với decorators (say_hello): Hàm say_hello được bao bọc bởi cả hai decorators. Đầu tiên là decorator2, sau đó là decorator1.
Output:
# Decorator 1
# Decorator 2
Hello!
6.3 Decorators tích hợp
Python cung cấp một số decorators tích hợp cho các nhiệm vụ tiêu chuẩn, chẳng hạn như static methods, class methods và properties.
@staticmethod
Decorator @staticmethod được dùng để tạo ra static method, không yêu cầu instance của class để gọi.
class MyClass:
@staticmethod
def static_method():
print("Đây là static method.")
MyClass.static_method()
@classmethod
Decorator @classmethod được dùng để tạo ra class method, nhận class (không phải instance) làm tham số đầu tiên.
class MyClass:
@classmethod
def class_method(cls):
print(f"Đây là class method {cls.__name__}.")
MyClass.class_method()
@property
Decorator @property được dùng để tạo ra getters, setters và deleters cho các thuộc tính.
class MyClass:
def __init__(self, value):
self.hidden_value = value
@property
def value(self):
return self.hidden_value
@value.setter
def value(self, new_value):
self.hidden_value = new_value
obj = MyClass(10)
print(obj.value) # Kết quả: 10
obj.value = 20
print(obj.value) # Kết quả: 20
Đây là các decorators tích hợp, và Python interpreter đảm bảo hoạt động đúng của chúng.
6.4 Ví dụ về sử dụng decorators
Logging
Decorators có thể được sử dụng để ghi lại các lần gọi hàm và phương thức.
def log_call(func):
def wrapper(*args, **kwargs):
print(f"Gọi hàm {func.__name__} với tham số {args} và {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_call
def add(x, y):
return x + y
print(add(2, 3))
Kiểm soát truy cập
Decorators có thể được sử dụng để kiểm soát truy cập vào các hàm và phương thức.
def require_authentication(func):
def wrapper(*args, **kwargs):
if not args[0].is_authenticated:
raise PermissionError("Người dùng không xác thực.")
return func(*args, **kwargs)
return wrapper
class User:
def __init__(self, is_authenticated):
self.is_authenticated = is_authenticated
@require_authentication
def view_profile(self):
print("Hồ sơ người dùng")
user = User(is_authenticated=True)
user.view_profile() # Gọi thành công
user2 = User(is_authenticated=False)
user2.view_profile() # PermissionError: Người dùng không xác thực.
Caching
Decorators có thể được sử dụng để lưu trữ kết quả của hàm.
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
GO TO FULL VERSION