1

我理解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

Q 1) 我的问题是,在 Test1 的 init 中声明的这个 name 属性是否绑定到 Test1 的实例...因为当我尝试获取 t1 的属性字典时,它返回空字典...

t1.__dict__
>>> {}

类 Test 的实例 t 相同

 t.__dict__
 >>> {}

当我向这些实例中的任何一个添加新属性时,就像这样......

 t.some = 'some'
 >>> t1.some = 'some'

再一次,如果我尝试访问属性字典,它只会给我我刚刚添加的内容。现在所有实例属性

t.__dict__
>>> {'some': 'some'}
>>> t1.__dict__
>>> {'some': 'some'}

Q 2) 那么在 init 中定义的实例属性(如类 Descriptor 和 Test 中的变量名和值)与在实例创建后定义的属性(如变量 t.some)有什么区别。

Q 3) Test 类与 Test1 类有何不同。

4

1 回答 1

3

in Test1your Descriptoris 并没有真正用作描述符,它只是一个名为 的普通属性name,恰好有一些特殊方法。但这并没有真正使它成为一个描述符。

如果您阅读有关如何调用描述符的文档,您将看到用于调用描述符方法的机制。在您的情况下,这意味着t.name将大致相当于:

type(t).__dict__['name'].__get__(t, type(t))

t1.name

type(t1).__dict__['name'].__get__(t1, type(t1))

name在类中查找__dict__,而不是在实例中查找,所以这就是区别所在,Test1.__dict__没有名为的描述符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

我认为你真正想做的是设置valueinstance不是self,这会让你得到预期的行为Test

于 2013-06-18T09:17:22.553 回答