Bạn có chắc chắn muốn xóa bài viết này không ?
Bạn có chắc chắn muốn xóa bình luận này không ?
Cài đặt thuộc tính lazy cho class trong Python
Thuộc tính lazy là gì?
Trước hết hãy xét tình huống sau:
Hệ thống backend của bạn có một User model. Mỗi một user được định danh bằng một access_token
- là môt unique private string.
Khi client gửi request tới backend, client phải gửi kèm theo access_token
.
Giờ nhiệm vụ của bạn là cần implement một APIRequest
class, nhận đầu vào là một dictionary (gồm GET params and POST data của HTTP request). Trong APIRequest
, bạn cần viết một hàm để xác định xem user nào đang thực hiện request.
Sau đây là một cách implement đơn giản
from app.models import User
class APIRequest(object):
def __init__(self, data):
self.data = data
self.access_token = data.get("access_token")
@property
def user(self):
user = User.find_user_by_access_token(self.access_token)
return user
Trong đó, User.find_user_by_access_token
sẽ thực hiện một query trong Database đề tìm ra user với access_token
được truyền vào.
Sau khi implement hàm user
xong, bạn nhận thấy, bạn muốn sử dụng hàm user
này rất nhiều lần khi xử lý request của user. Nhưng mỗi lần gọi hàm user
, việc gọi tới database là rất tốn chi phí, thế nên bạn sẽ muốn cache kết quả này lại.
Do đó, bạn chỉnh sửa lại hàm user
như sau
@property
def user(self):
if not hasattr(self, "_user"):
self._user = User.find_user_by_access_token(self.access_token)
return self._user
Bằng việc cached lại giá trị của user vào thuộc tính self._user
, bạn sẽ chỉ cần query vào Database đúng lần đầu khi bạn gọi hàm APIRequest.user
.
Thuộc tính user
của APIRequest trong trường hợp này được gọi là lazy property
(lazy nghĩa chỉ là chạy khi được gọi, và chỉ chạy đúng 1 lần)
Implement lazy property
Lazy property khá hữu dụng trong nhiều trường hợp. Tuy nhiên, việc lặp đi lặp lại cách implement khá là nhàm chán.
Bạn tưởng tượng, với mỗi một lazy property, chúng ta đều phải code những đoạn code như sau:
if not hasattr(self, "some_value"):
self._some_value = do_something()
return self._some_value
Bằng decorator
, tôi sẽ implement một lazy property như sau
# file libs/decorators.py
def lazy(func):
attr_name = "_lazy_%s" % func.__name__
@property
def wrapper(self):
if not hasattr(self, attr_name):
setattr(self, attr_name, func(self))
return getattr(self, attr_name)
@wrapper.setter
def wrapper(self, value):
setattr(self, attr_name, value)
return wrapper
Với cách này, mỗi khi muốn sử dụng lazy property
, tôi chỉ cần
from libs.decorators import lazy
class APIRequest(object):
@lazy
def user(self):
return User.find_user_by_access_token(self.access_token)
Decorator rất là hữu dụng khi làm việc với Python.
Ngoài lazy property, decorator còn có nhiều ứng dụng khác.
Nếu muốn tìm hiểu thêm về các user cases của decorator, các bạn có thể tham khảo
- cách thư viện celery implement
task
decorators - cách flask implement các decorators routes







