Để hỗ trợ phân bổ thuộc tính tùy ý, đối tượng cần có một __dict__
: một dict được liên kết với đối tượng, nơi có thể lưu trữ thuộc tính tùy ý. Nếu không, không có nơi nào để đặt thuộc tính mới.
Một thể hiện của object
không không carry xung quanh 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, được thừa hưởng từ object
;-), điều này sẽ yên mỗi đối tượng trong Python với dict, có nghĩa là chi phí của nhiều byte cho mỗi đối tượng hiện không có hoặc không có lệnh dict (về cơ bản, tất cả các đối tượng không có thuộc tính được gán tùy ý không có hoặc cần lệnh).
Ví dụ, bằng cách sử dụng dự án xuất sắc pympler
(bạn có thể lấy nó qua svn từ here), chúng ta có thể làm 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 int
để mất 144 byte thay vì chỉ 16, phải -)
Bây giờ, khi bạn thực hiện một lớp (kế thừa từ bất cứ điều gì), mọi thứ thay đổi ...:?
>>> class dint(int): pass
...
>>> asizeof.asizeof(dint(23))
184
... __dict__
là hiện đã được thêm (cộng thêm một chút chi phí) - vì vậy một cá thể dint
có thể có các thuộc tính tùy ý, nhưng bạn phải trả một khoản chi phí không gian cho tính linh hoạt đó.
Vì 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 rất hiếm, nhưng Python không đưa ra một cơ chế đặc biệt cho mục đích này ...
>>> class fint(int):
... __slots__ = 'foobar',
... def __init__(self, x): self.foobar=x+100
...
>>> asizeof.asizeof(fint(23))
80
... không khá nhỏ như một int
, tâm trí bạn! (hoặc thậm chí hai số int
s, một trong số self
và một số self.foobar
- thứ hai có thể được gán lại), nhưng chắc chắn tốt hơn nhiều so với dint
.
Khi lớp có __slots__
thuộc tính đặc biệt (một chuỗi các chuỗi), sau đó các class
statement (chính xác hơn, các metaclass mặc định, type
) không không trang bị cho tất cả các thể hiện của lớp đó với 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 "khe" hữu hạn, cứng nhắc (về cơ bản những nơi 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 tính linh hoạt bị mất, bạn nhận được nhiều byte cho mỗi trường hợp (có thể chỉ có ý nghĩa nếu bạn có hàng chục trường hợp gấp rút xung quanh, nhưng, có là trường hợp sử dụng cho điều đó).
phỏng đoán thuần túy: Loại 'đối tượng' 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. –
@ S.Lott: Xem dòng đầu tiên của câu hỏi này. Hoàn toàn tò mò. – Smashery
Tiêu đề của bạn là gây hiểu lầm, bạn đang cố gắng thiết lập các thuộc tính trên các cá thể lớp 'object', không phải trên lớp' object'. – dhill