2012-09-19 41 views
3

考慮以下Python代碼:的Python:超載__getattr__和性能,使得__setattr__正常工作

class Foo(object): 

    def __init__(self, value): 
     self._value = value 

    @property 
    def value(self): 
     return "value: {v}".format(v=self._value) 

    @value.setter 
    def value(self, value): 
     self._value = value 

class Bar(object): 

    def __init__(self): 
     self.foo = Foo('foo') 

    def __getattr__(self, attr, *args, **kwargs): 
     """ 
     Intercepts attribute calls, and if we don't have it, look at the 
     webelement to see if it has the attribute. 
     """ 

     # Check first to see if it looks like a method, if not then just return 
     # the attribute the way it is. 
     # Note: this has only been tested with variables, and methods. 
     if not hasattr(getattr(self.foo, attr), '__call__'): 
      return getattr(self.foo, attr) 

     def callable(*args, **kwargs): 
      ''' 
      Returns the method from the webelement module if found 
      ''' 
      return getattr(self.foo, attr)(*args, **kwargs) 
     return callable 

>>> b = Bar() 
>>> b.foo 
<__main__.Foo object at 0x819410> 
>>> b.foo.value 
'value: foo' 
>>> b.foo.value = '2' 
>>> b.foo.value 
'value: 2' 
>>> b.value 
'value: 2' 
>>> b.value = '3' 
>>> b.value 
'3' 

這最後一部分,我希望它是「值:3」,而不是「3」,因爲現在我的屬性'值'現在是一個屬性。

是否有可能,如果是我會怎麼做。

回答

3

您的__getattr__返回屬性,而不是屬性本身。當您訪問getattr(self.foo, attr)時,它會執行self.foo.value的等價操作並返回該值,並在此時調用該屬性。

因此,您也需要實施__setattr__方法來鏡像__getattr__並將值設置傳遞給包含的foo對象。

在引擎蓋下,Python實現了屬性descriptors;它們的__get__() method由較低級別__getattribute__ method調用,這會導致它們返回它們的計算值。它從來不是返回的屬性對象本身。

下面是一個例子__setattr__

def __setattr__(self, attr, value): 
    if hasattr(self, 'foo') and hasattr(self.foo, attr): 
     setattr(self.foo, attr, value) 
     return 
    super(Bar, self).__setattr__(attr, value) 

注意:您__init__self.foo,你需要測試是否存在對你的類(hasattr(self, 'foo')foo您還需要調用原來__setattr__執行,以確保。像self.foo = Foo()工作仍然工作

+0

那麼我該如何實現這樣的__setattr__。我試過但不知道如何正確地做到這一點。謝謝Martijn! – glouie

+0

@glouie:增加了一個例子'__seta ttr__'爲你。 –

+0

這樣做!非常感謝! – glouie