2013-10-24 14 views
5

Nói rằng tôi có một lớp học trong đó xác định __slots__:__setattr __() có thể được định nghĩa trong một lớp với __slots__ không?

class Foo(object): 
    __slots__ = ['x'] 

    def __init__(self, x=1): 
     self.x = x 

    # will the following work? 
    def __setattr__(self, key, value): 
     if key == 'x': 
      object.__setattr__(self, name, -value) # Haha - let's set to minus x 

Tôi có thể xác định __setattr__() cho nó?

Foo không có __dict__, nó sẽ cập nhật những gì?

Trả lời

9

Tất cả mã của bạn, ngoài việc phủ nhận giá trị, hãy gọi cho lớp cha __setattr__, đó chính là điều sẽ xảy ra mà không có phương thức __setattr__ của bạn. Vì vậy, câu trả lời ngắn gọn là: Chắc chắn bạn có thể xác định một __setattr__.

Những gì bạn không thể làm là xác định lại __setattr__ sử dụng self.__dict__, vì trường hợp của một lớp học với khe không một thuộc tính __dict__. Nhưng các trường hợp như vậy do có thuộc tính self.x, nội dung của nó không được lưu trữ trong từ điển trên cá thể.

Thay vào đó, giá trị vị trí được lưu trữ ở cùng một vị trí, __dict__ từ điển thể hiện nếu không sẽ được lưu trữ; trên heap đối tượng. Không gian được dành riêng cho các tài liệu tham khảo len(__slots__)descriptors trên lớp truy cập các tham chiếu này nhân danh bạn.

Vì vậy, trong một cái móc __setattr__, bạn có thể chỉ cần gọi những mô tả trực tiếp thay vì:

def __setattr__(self, key, value): 
    if key == 'x': 
     Foo.__dict__[key].__set__(self, -value) 

Thú đường vòng: yes, trên lớp học mà không có một thuộc tính __slots__, có một mô tả rằng sẽ cung cấp cho bạn truy cập đến đối tượng __dict__ các trường hợp:

>>> class Bar(object): pass 
... 
>>> Bar.__dict__['__dict__'] 
<attribute '__dict__' of 'Bar' objects> 
>>> Bar.__dict__['__dict__'].__get__(Bar(), Bar) 
{} 

đó là cách bình thường trường hợp có thể nhìn lên self.__dict__. Mà làm cho bạn tự hỏi, nơi các đối tượng Bar.__dict__ được tìm thấy. Trong Python, nó là turtles all the way down, bạn muốn tìm rằng đối tượng lên trên các đối tượng type tất nhiên:

>>> type.__dict__['__dict__'] 
<attribute '__dict__' of 'type' objects> 
>>> type.__dict__['__dict__'].__get__(Bar, type) 
dict_proxy({'__dict__': <attribute '__dict__' of 'Bar' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Bar' objects>, '__doc__': None}) 
+0

không __dict__ làm việc ở đây? là bởi vì địa chỉ hiệu quả của __dict__ và các mục heap là như nhau, và đây là loại trứng phục sinh? hoặc bạn có nghĩa là __slots__? –

+0

@CorleyBrigman: đừng nhầm lẫn giữa '__dict__' của ** class ** với ** ** instance **. Các cá thể của lớp 'Foo' không có thuộc tính' __dict__'. –

+0

@CorleyBrigman: Và các trường hợp 'Foo' không có thuộc tính' __dict__', bởi vì 'Foo .__ dict __ ['__ dict __']' đặt ra một 'KeyError'. –

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