2011-01-23 65 views
5

Định nghĩa __setattr__ ghi đè tất cả các phương thức/thuộc tính setter mà tôi định nghĩa trong một lớp. Tôi muốn sử dụng các phương thức setter được xác định trong thuộc tính, nếu một thuộc tính tồn tại cho một trường và sử dụng self.__dict__[name] = value nếu không.Tôi cần xác định __setattr__ để gán các trường không có thuộc tính, nhưng sử dụng hàm setter/getter cho các trường có thuộc tính được xác định

Trợ giúp! Tôi đã tìm thấy một giải pháp đã sử dụng __setitem__, nhưng cách này không hiệu quả đối với tôi

Thuộc tính được lưu trữ trong lớp python ở đâu? Làm cách nào để truy cập chúng?

Làm cách nào để xác định __setattr__ để nó sử dụng thuộc tính cho các trường có phương thức setter được xác định?

class test(object): 

def _get_gx(self): 
    print "get!" 
    return self.__dict__['gx'] 

def _set_gx(self, gx): 
    print "set!" 
    self.__dict__['gx'] = gx 
    gx = property(_get_gx, _set_gx) 

def __setattr__(self, name, value): 
    self.__dict__[name] = value 

def __init__(self): 
    pass 

cũng có,

Tại sao là "có được!" được in hai lần khi tôi làm,

x = test() 
x.gx = 4 
x.gx 

prints: 

    "gets!" 
    "gets!" 
    4 
+0

Sẽ rất khó để làm việc này với sự thụt đầu dòng của bạn bị hỏng. Câu hỏi chung duy nhất mà bạn hỏi mặc dù là "nơi các nhà mô tả sống" và câu trả lời nằm trong dict của lớp. – aaronasterling

+0

Họ không có trong từ điển lớp học. Các thuộc tính mà tôi xác định, không hiển thị trong từ điển lớp. – HaltingState

+1

Sau đó, bạn đang làm điều gì sai. Mô tả trực tiếp trong từ điển lớp. Nhìn vào mô hình dữ liệu python để biết chi tiết. Nếu bạn sửa chữa thụt đầu dòng của bạn, tôi sẽ tìm ra nó cho bạn. – aaronasterling

Trả lời

10

Bạn cần phải viết lại hàm __setattr__ của mình. Theo docs, các lớp kiểu mới nên sử dụng baseclass.__setattr__(self, attr, value) thay vì self.__dict__[attr] = value. Các cựu sẽ tra cứu bất kỳ descriptors trong khi sau này sẽ chỉ định trực tiếp cho dict.

Vì vậy, viết lại phương pháp của bạn như

def __setattr__(self, name, value): 
    object.__setattr__(self, name, value) 

hoặc

def __setattr__(self, name, value): 
    super(Test, self).__setattr__(name, value) 

và bạn sẽ ổn thôi. Mã

class Test(object): 
    @property 
    def gx(self): 
     print "getting gx" 
     return self.__dict__['gx'] 

    @gx.setter 
    def gx(self, value): 
     print "setting gx" 
     self.__dict__['gx'] = value 

    def __setattr__(self, attr, value): 
     print "using setattr"    
     object.__setattr__(self, attr, value) 

t = Test() 
t.gx = 4 
t.dummy = 5 
print t.gx 
print t.dummy 

print dir(Test) 

đầu ra

using setattr 
setting gx 
getting gx 
using setattr 
4 
5 
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gx'] 

Tôi không biết lý do tại sao phiên bản của bạn đang kêu gọi các getter hai lần. Cái này thì không. Ngoài ra, để trả lời câu hỏi của bạn về nơi mô tả trực tiếp, bạn có thể thấy rõ ràng đó là mục nhập cuối cùng trong dict lớp.

Cần lưu ý rằng bạn không cần __setattr__ để thực hiện những gì bạn muốn trong ví dụ của mình. Python sẽ luôn viết một bài tập foo.bar = x đến foo.__dict__['bar'] = x bất kể có mục nhập trong số foo.__dict__ hay không. __setattr__ là khi bạn muốn chuyển đổi giá trị hoặc đăng nhập nhiệm vụ hoặc một cái gì đó tương tự.

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