如何确定描述符的类?

时间:2017-03-08 16:19:57

标签: python

在此示例代码中,我想确定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 个答案:

答案 0 :(得分:3)

使用当前__get__Test.x会导致AttributeError,因为当使用类instance访问描述符的代码传递None时; (=&gt; getattr(None, 'x') =&gt; 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
正如您所知,BTW,x = TestProperty("x"),通过实例访问x属性会导致另一个异常,因为它会调用__get__( - &gt; getattr(.. ) - &gt; __get__ - &gt; getattr(..) - &gt; ...)递归直到堆栈溢出。

答案 1 :(得分: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。 请参阅https://docs.python.org/3/library/functions.html#property上的@property文档。