behaviour of descriptor concept in python (confusing)

大城市里の小女人 提交于 2019-12-19 10:47:36

问题


I understood python descriptor but I have a little confusion about this..

if you have a class descriptor as follows

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

and a class whose attributes we want to manage is something like this..

class Test(object):
    name = Descriptor()
    def __init__(self, name):
        print 'init test'
        self.name = name

when I create object of class Test and do something it gives me answer like this...

t = Test('abc')
init test
setting
>>> t.name
getting 
'abc'
>>> del t.name
deleting
>>> t
<__main__.Test object at 0x013FCCD0>
>>> t.name
getting 

Now I want to have a class Test1 something like this..

class Test1(object):
    def __init__(self, value):
        print 'init test1'
        self.name = Descriptor()
        self. value = value

and if I create object of Test1 and try to access attribute of instance of Test1, I get output something like this..

t1 = Test1(12)
t1.name
>>> getting
>>> 12
>>> t1.name = 30
>>> setting

Q 1) my question is that is this name attribute declared in init of Test1, is bound to instance of Test1 or not... because when I try to get attribute dictionary of t1, it return empty dict...

t1.__dict__
>>> {}

same for class Test's instance t

 t.__dict__
 >>> {}

When I add a new attribute to any of these instances, like this...

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

and again if I try to access attribute dictionary it gives me only which I have added just now.. now all instance attribute

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

Q 2) So what is the difference between instance attributes defined in init (like variable name and value in class Descriptor and Test) and attributes defined after instance creation (like variable t.some).

Q 3) How class Test is different than class Test1.


回答1:


In Test1 your Descriptor isn't really used as a descriptor, it's just a normal attribute called name, that happens to have some the special methods. But that doensn't really make it a descriptor yet.

If you read the docs about how descriptors are invoked, youll see the mechanism that is used to invoke the descriptors methods. In your case this would mean t.name woud be roughly equivalent to:

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

and t1.name:

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

name is looked up in the __dict__ of the class, not of the instance, so that's where the difference is, Test1.__dict__ doesn't have a descriptor called 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'

What you also should consider, is that your descriptor sets the value attribute on itself, that means all instances of Test will share the same value:

>>> 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

I think that what yo acutally want to do is to set value on instance instead of self, that would get you the expected behaviour in Test.



来源:https://stackoverflow.com/questions/17164029/behaviour-of-descriptor-concept-in-python-confusing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!