2014-05-08 16 views
5

Giả sử tôi có một lớp và tôi muốn tạo nhiều thuộc tính "kiểu thuộc tính" tương tự. Ví dụ:Tôi có nên sử dụng lớp mô tả hoặc nhà máy sản xuất bất động sản không?

class Foo(object): 
    @property 
    def foo(self): 
     return self._foo 

    @foo.setter 
    def foo(self, val): 
     self.update() 
     self._foo = val 

    @property 
    def bar(self): 
     return self._bar 

    @bar.setter 
    def bar(self, val): 
     self.update() 
     self._bar = val 

    @property 
    def baz(self): 
     return self._baz 

    @baz.setter 
    def baz(self, val): 
     self.update() 
     self._baz = val 

    def update(self): 
     print "Updating..." 

Rõ ràng là có rất nhiều sự lặp lại ở đây và sẽ rất tuyệt khi tính yếu tố đó. Một cách sẽ được thực hiện một hàm trả về một tài sản:

def create_property(var): 
    def _setter(self, val): 
     self.update() 
     setattr(self, '_' + var, val) 

    def _getter(self): 
     return getattr(self, '_' + var) 

    return property(_getter, _setter) 

class Foo(object): 
    foo = create_property("foo") 
    bar = create_property("bar") 
    baz = create_property("baz") 

    def update(self): 
     print "Updating..." 

Ngoài ra tôi có thể viết một lớp mô tả:

class UpdateOnChange(object): 
    def __init__(self): 
     self.data = WeakKeyDictionary() 

    def __get__(self, instance, owner): 
     try: 
      return self.data[instance] 
     except KeyError: 
      raise AttributeError("attribute not set") 

    def __set__(self, instance, value): 
     instance.update() 
     self.data[instance] = value 

class Foo(object): 
    foo = UpdateOnChange() 
    bar = UpdateOnChange() 
    baz = UpdateOnChange() 

    def update(self): 
     print "Updating" 

nào là tốt nhất/nhanh nhất/nhất Pythonic?

+2

Trình mô tả có chính xác điều này. Vì vậy, * theo ý kiến ​​của tôi *, bạn nên sử dụng các bộ mô tả. Tôi đã in nghiêng mục đích này để làm nổi bật rằng đây chủ yếu là dựa trên ý kiến. Bỏ phiếu để giữ, như chủ yếu dựa trên ý kiến ​​ – J0HN

+0

Tôi muốn đề nghị trang trí quá. Mặc dù nếu bạn kết hợp với một metaclass, bạn có thể tự động nhập tên của các biến lớp để xây dựng bộ mô tả, do đó giảm bớt sự cần thiết cho từ điển 'self.data'. Điều đó sẽ tốt hơn một chút đối với bộ nhớ và chi phí hoạt động, nhưng có lẽ quan trọng hơn, bạn sẽ không bao giờ phải đối phó với các va chạm chính hoặc hành vi kỳ quặc trong trường hợp tham chiếu chết. –

Trả lời

0

Lấy ý tưởng mô tả và trộn nó với một metaclass, như tôi đã đề cập trong phần bình luận.

class UpdateOnChange(object): 
    def __init__(self, name): 
     self.name = name 
     self._name = '_' + name 

    def __get__(self, instance, owner): 
     try: 
      return getattr(instance, self._name) 
     except AttributeError: 
      raise AttributeError('%s has no attribute %s.' % (instance, self.name)) 

    def __set__(self, instance, value): 
     # Assume first assignment is initialization and does not require update. 
     if not hasattr(instance, self._name): 
      setattr(instance, self._name, value) 
     else: 
      instance.update() 
      setattr(instance, self._name, value) 

class UpdateOnChangeMeta(type): 

    def __new__(cls, name, bases, attrs): 
     for attr_name in attrs: 
      if attrs[attr_name] == UpdateOnChange: 
       attrs[attr_name] = UpdateOnChange(attr_name) 
     return type.__new__(cls, name, bases, attrs) 

class Foo(object): 

    __metaclass__ = UpdateOnChangeMeta 
    foo = UpdateOnChange 
    bar = UpdateOnChange 
    baz = UpdateOnChange 

    def update(self): 
     print "Updating" 
Các vấn đề liên quan