2011-10-27 28 views
8

Thông thường, bạn có thể thiết lập một thuộc tính tùy ý để một đối tượng tùy chỉnh, ví dụKhông thể đặt thuộc tính thành chuỗi?

---------- 
>>> a=A() 
>>> a.foo=42 
>>> a.__dict__ 
{'foo': 42} 
>>> 
---------- 

Mặt khác, bạn không thể làm điều tương tự ràng buộc với một đối tượng chuỗi:

---------- 
>>> a=str("bar") 
>>> a.foo=42 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'str' object has no attribute 'foo' 
>>> a.__dict__ 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'str' object has no attribute '__dict__' 
>>> 
---------- 

Tại sao ?

Trả lời

9

Vì loại str là loại không có thuộc tính. Từ the docs, phần "Lớp học":

Lớp học có không gian tên được thực hiện bởi đối tượng từ điển. tài liệu tham khảo thuộc tính Class được dịch sang tra cứu trong từ điển này, ví dụ như, C.x được phiên dịch sang C.__dict__["x"]

Bạn cũng có thể thực thi một cái gì đó tương tự như trên các đối tượng tùy chỉnh:

>>> class X(object): 
...  __slots__=('a',) 
... 
>>> a = X() 
>>> a.a = 2 
>>> a.foo = 2 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'X' object has no attribute 'foo' 

Nói chung, bạn không nên thiết lập và sửa đổi các trường của các đối tượng mà bạn không phải làm. Tài liệu về loại dữ liệu cụ thể sẽ tham chiếu cho bạn những trường nào có sẵn để sửa đổi công khai.

Ví dụ, một đối tượng ReadOnlyPoint, nơi tọa độ x và y được thiết lập chỉ xây dựng đối tượng:

>>> class ReadOnlyPoint(object): 
...  __slots__ = ('_x', '_y') 
...  def __init__(self, x, y): 
...    self._x = x 
...    self._y = y 
...  def getx(self): 
...    return self._x 
...  def gety(self): 
...    return self._y 
...  x = property(getx) 
...  y = property(gety) 
... 
>>> p = ReadOnlyPoint(2, 3) 
>>> print p.x, p.y 
2 3 
>>> p.x = 9 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: can't set attribute 
>>> p._x = 9 
>>> print p.x, p.y 
9 3 

Trong khi xy tính là chỉ đọc, truy cập vào internals đối tượng cho phép bạn thay đổi trạng thái của đối tượng.

Khả năng không thể thêm trường mới vào đối tượng str là chi tiết triển khai, cụ thể cho phiên bản Python bạn đang sử dụng.

+0

Không phải là nó là kết quả của một thực tế rằng 'loại str' được về cơ bản thiết kế như bất biến? Nếu bạn tạo một lớp (lớp trống, như trong ví dụ của tôi) kế thừa từ 'str', bạn sẽ không nhận được lỗi được đề cập. Đối với tuple tuy nhiên bạn sẽ nhận được lỗi này (chúng cũng không thay đổi). – Tadeck

+0

@Tadeck Vâng, cả hai lý do đều thành hiện thực - chuỗi được tích hợp và không có '__dict__', giống như các lớp do người dùng định nghĩa với' __slots__' modulo [cạnh trường hợp] (http: //docs.python. org/py3k/reference/datamodel.html # notes-on-using-slots). Nó cũng sẽ không hỗ trợ gán thuộc tính dù là các chuỗi không thay đổi. Điều đó cũng có thể được nhìn thấy trong thông báo lỗi thứ hai của OP ("đối tượng str không có thuộc tính __dict__"). – delnan

+4

@Tadeck Nó có _nothing_ để làm với khả năng biến đổi. Hãy thử nó với một 'danh sách', bạn sẽ nhận được kết quả tương tự. Bạn không thể làm điều đó với bất kỳ kiểu dựng sẵn cơ bản nào – agf

Các vấn đề liên quan