在此示例代码中,我想确定x
是TestProperty
的实例:
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'
无论如何,当它是一个描述符时,是否有一个属性是一个类的实例?
答案 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
文档。