我理解python描述符,但我对此有点困惑..
如果你有一个类描述符如下
class Descriptor(object):
def __get__(self, instance, owner):
print 'getting'
return self.value
def __set__(self, instance, value):
print 'setting'
self.value = value
def __delete__(self, instance):
print 'deleting'
del self.value
和我们想要管理其属性的类是这样的..
class Test(object):
name = Descriptor()
def __init__(self, name):
print 'init test'
self.name = name
当我创建类Test的对象并执行某些操作时,它会给我这样的答案......
t = Test('abc')
init test
setting
>>> t.name
getting
'abc'
>>> del t.name
deleting
>>> t
<__main__.Test object at 0x013FCCD0>
>>> t.name
getting
现在我想要一个像这样的类Test1 ..
class Test1(object):
def __init__(self, value):
print 'init test1'
self.name = Descriptor()
self. value = value
如果我创建Test1的对象并尝试访问Test1实例的属性,我得到类似这样的输出..
t1 = Test1(12)
t1.name
>>> getting
>>> 12
>>> t1.name = 30
>>> setting
问题1)我的问题是这是在Test1的init中声明的这个名称属性,是否绑定到Test1的实例...因为当我尝试获取t1的属性字典时,它返回空字典... < / p>
t1.__dict__
>>> {}
类Test的实例t
t.__dict__
>>> {}
当我向这些实例中添加新属性时,就像这样...
t.some = 'some'
>>> t1.some = 'some'
再次如果我尝试访问属性字典,它只给我我刚刚添加的内容..现在所有实例属性
t.__dict__
>>> {'some': 'some'}
>>> t1.__dict__
>>> {'some': 'some'}
问2)那么init中定义的实例属性(如变量名和类Descriptor和Test中的值)与实例创建后定义的属性(如变量t.some)之间的区别是什么。
问题3)Class Test如何与Test1类不同。
答案 0 :(得分:3)
在Test1
中你的Descriptor
并没有真正用作描述符,它只是一个名为name
的普通属性,碰巧有一些特殊的方法。但那确实还没有成为一个描述符。
如果read the docs关于如何调用描述符,您将看到用于调用描述符方法的机制。在你的情况下,这意味着t.name
大致相当于:
type(t).__dict__['name'].__get__(t, type(t))
和t1.name
:
type(t1).__dict__['name'].__get__(t1, type(t1))
name
在类的__dict__
中查找,而不是实例,因此差异在于Test1.__dict__
没有名为{{1}的描述符}:
name
您还应该考虑的是,您的描述符会在其自身设置>>> Test.__dict__['name']
<__main__.Descriptor object at 0x7f637a57bc90>
>>> Test1.__dict__['name']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'name'
属性,这意味着value
的所有实例将共享相同的值:
Test
我认为您真正想要做的是在>>> t1 = Test(1)
init test
setting
>>> t2 = Test(2)
init test
setting
>>> t1.name
getting
2
>>> t2.name
getting
2
>>> t1.name = 0
setting
>>> t2.name
getting
0
上设置value
而不是instance
,这样可以在self
中获得预期的行为。