2017-03-08 95 views
1

在這個例子中的代碼,我想,以確定是否xTestProperty一個實例:如何確定描述符的類?

class TestProperty(object): 
    def __init__(self, name): 
     self._name = name 

    def __get__(self, instance, cls): 
     return getattr(instance, self._name) 

    def __set_(self, instance, value): 
     setattr(instance, self._name, value) 

class Test(object): 
    x = TestProperty("x") 

print isinstance(Test.x, TestProperty) 

不過,我得到以下異常:

Traceback (most recent call last): 
    File "/home/zenoss/testproperties.py", line 14, in <module> 
    print isinstance(Test.x, TestProperty) 
    File "/home/zenoss/testproperties.py", line 6, in __get__ 
    return getattr(instance, self._name) 
AttributeError: 'NoneType' object has no attribute 'x' 

反正是有說,如果一個屬性當它是一個描述符時,它是一個類的實例嗎?

回答

2

隨着當前__get__Test.x使AttributeError因爲當訪問使用類的描述符的代碼,instance傳遞None; (=>getattr(None, 'x') =>None.x

您應修改__get__來處理這種情況:

>>> class TestProperty(object): 
...  def __init__(self, name): 
...   self._name = name 
...  def __get__(self, instance, cls): 
...   if instance is None: # To handle access through class, not instance 
...    return self  # returns the TestProperty instance itself. 
...   return getattr(instance, self._name) 
...  def __set_(self, instance, value): 
...   setattr(instance, self._name, value) 
... 
>>> class Test(object): 
...  x = TestProperty("x") 
... 
>>> isinstance(Test.x, TestProperty) 
True 

順便說一句,你可能知道,隨着x = TestProperty("x"),訪問x屬性通過一個實例會導致另一個異常,因爲它會遞歸地調用__get__( - > getattr(..) - > __get__ - > getattr(..) - > ...),直到堆棧溢出。

+0

謝謝,當'實例是None'時返回'self'會有訣竅。 – Ben

+0

@本,不客氣。快樂的Python黑客! – falsetru

0

實現財產的最好方式是與@property裝飾:

class TestProperty(object): 

    def __init__(self, name): 
     self._name = name 

    @property 
    def name(self): 
     """Getter for '_name'.""" 
     return self._name 

    @name.setter 
    def name(self, value): 
     """Setter for '_name'.""" 
     self._name = value 

class Test(object): 
    x = TestProperty("x") 

print(isinstance(Test.x, TestProperty)) 

它返回True當我運行它。 請參閱@property的文檔https://docs.python.org/3/library/functions.html#property