Slots là cách để đi:
Cách pythonic là sử dụng các khe thay vì chơi xung quanh __setter__
. Mặc dù nó có thể giải quyết vấn đề, nhưng nó không cải thiện hiệu suất. Các thuộc tính của các đối tượng được lưu trữ trong một từ điển " __dict__
", đây là lý do, tại sao bạn có thể thêm động các thuộc tính vào các đối tượng của các lớp mà chúng tôi đã tạo cho đến nay. Việc sử dụng từ điển để lưu trữ thuộc tính rất thuận tiện, nhưng nó có thể gây lãng phí không gian cho các đối tượng chỉ có một lượng nhỏ biến cá thể.
Khe cắm là một cách tốt để giải quyết vấn đề tiêu thụ không gian này. Thay vì có một lệnh động cho phép thêm các thuộc tính động vào các đối tượng, các vị trí cung cấp một cấu trúc tĩnh ngăn cấm việc bổ sung sau khi tạo một thể hiện.
Khi chúng tôi thiết kế một lớp, chúng tôi có thể sử dụng các vị trí để ngăn việc tạo động các thuộc tính. Để xác định vị trí, bạn phải xác định danh sách với tên __slots__
. Danh sách phải chứa tất cả các thuộc tính mà bạn muốn sử dụng. Chúng tôi chứng minh điều này trong lớp sau, trong đó danh sách vị trí chỉ chứa tên cho một thuộc tính "val".
class S(object):
__slots__ = ['val']
def __init__(self, v):
self.val = v
x = S(42)
print(x.val)
x.new = "not possible"
=> Không tạo được thuộc tính "new":
42
Traceback (most recent call last):
File "slots_ex.py", line 12, in <module>
x.new = "not possible"
AttributeError: 'S' object has no attribute 'new'
NB:
- Kể từ Python 3.3, lợi thế tối ưu hóa tiêu thụ không gian không còn ấn tượng nữa. Với Python 3.3 , Từ điển chia sẻ khóa được sử dụng để lưu trữ các đối tượng. Các thuộc tính của các cá thể có khả năng chia sẻ một phần bộ nhớ trong của chúng với nhau, tức là phần lưu trữ các khóa và các hàm băm tương ứng của chúng. Điều này giúp giảm mức tiêu thụ bộ nhớ của các chương trình, vốn tạo ra nhiều trường hợp của các loại không phải nội trang. Nhưng vẫn là cách để tránh các thuộc tính được tạo động.
- Sử dụng khe cắm cũng có chi phí riêng. Nó sẽ phá vỡ tuần tự hóa (ví dụ: dưa chua). Nó cũng sẽ phá vỡ đa kế thừa. Một lớp không thể kế thừa từ nhiều hơn một lớp xác định vị trí hoặc có bố cục cá thể được xác định trong mã C (như danh sách, tuple hoặc int).
__setattr__
nhưng điều đó có thể sẽ rất khó.