Để hỗ trợ việc gán thuộc tính tùy ý, một đối tượng cần có __dict__
: một dict liên kết với đối tượng, nơi các thuộc tính tùy ý có thể được lưu trữ. Nếu không, không có nơi nào để đặt các thuộc tính mới.
Một thể hiện của object
không không mang theo một __dict__
- nếu nó đã làm, trước khi vấn đề phụ thuộc tròn khủng khiếp (vì dict
, giống như hầu hết mọi thứ khác, thừa hưởng từ object
;-), điều này sẽ yên mỗi đối tượng trong Python với một dict, trong đó sẽ có nghĩa là một overhead của nhiều byte cho mỗi đối tượng mà hiện không có hoặc cần một dict (về cơ bản, tất cả các đối tượng mà không có tùy tiện thuộc tính chuyển nhượng không có hoặc cần một dict).
Ví dụ, bằng cách sử dụng pympler
dự án xuất sắc (bạn có thể lấy nó qua svn từ đây ), chúng tôi có thể thực hiện một số phép đo ...:
>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16
Bạn sẽ không muốn mọi thứ int
chiếm 144 byte thay vì chỉ 16, phải không? -)
Bây giờ, khi bạn tạo một lớp (kế thừa từ bất cứ thứ gì), mọi thứ sẽ thay đổi ...:
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
... những __dict__
là hiện nay gia tăng (cộng, một chút chi phí hơn) - do đó, một dint
ví dụ có thể có các thuộc tính tùy ý, nhưng bạn phải trả khá một chi phí không gian cho sự linh hoạt đó.
Vậy nếu bạn muốn int
s chỉ với một thuộc tính bổ sung foobar
...? Đó là một nhu cầu hiếm hoi, nhưng Python cung cấp một cơ chế đặc biệt cho mục đích ...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
... không hoàn toàn nhỏ như một int
, phiền bạn! (hoặc thậm chí hai int
s, một cái self
và một cái self.foobar
- cái thứ hai có thể được gán lại), nhưng chắc chắn tốt hơn nhiều so với a dint
.
Khi lớp có __slots__
thuộc tính đặc biệt (một chuỗi các chuỗi), thì class
câu lệnh (chính xác hơn là siêu kính mặc định, type
) không trang bị cho mọi cá thể của lớp đó một __dict__
(và do đó khả năng có các thuộc tính tùy ý), chỉ là một , tập hợp các "khe" cứng nhắc (về cơ bản là các vị trí mà mỗi vị trí có thể chứa một tham chiếu đến một số đối tượng) với các tên đã cho.
Để đổi lấy sự linh hoạt bị mất, bạn nhận được rất nhiều byte cho mỗi phiên bản (có thể chỉ có ý nghĩa nếu bạn có nhiều phiên bản liên quan xung quanh, nhưng, có những trường hợp sử dụng cho điều đó).
object
Loại là bất biến và không thể thêm thuộc tính mới? Điều này có vẻ như nó sẽ có ý nghĩa nhất.