0

This a simple class, i just want to test the feature about __get__() The code is :

class Des(object):
    def __init__(self,num):
        self.num = num
    def __get__(self, obj, typ = None):
        return self.num

class A(object):
    des = Des(1)
    print 'the des in class is ',des

a = A()
print  'the des in object is ',a.des
print a.__dict__
print A.__dict__

the output is :

the des in class is  <Des object at 0x7f5fb550ded0>
the des in object is  1
{}
{'__dict__': <attribute '__dict__' of 'A' objects>, '__module__': '__builtin__', 'des': <Des object at 0x7f5fb550ded0>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}

my question is why the why the outputs of des are des is different (one is 1 type(int), one is object type(Des)). And the output of a.__dict__ and A.__dict is also different. What's the fucntion of __get__(), and how to use it.

smci
  • 32,567
  • 20
  • 113
  • 146
  • 3
    Where did you get the idea that `__get__` has anything to do with attributes and `__dict__`? It is part of the *descriptor protocol*; binding methods and properties. – Martijn Pieters Jun 29 '15 at 07:38
  • How much do you already understand of descriptors? Does my [answer on `property` objects](https://stackoverflow.com/questions/17330160/how-does-the-property-decorator-work/17330273#17330273) help here at all? – Martijn Pieters Jun 29 '15 at 07:40
  • and perhaps [Descriptors and direct access: Python reference](https://stackoverflow.com/q/19409373) is relevant here too. – Martijn Pieters Jun 29 '15 at 07:48
  • try `a = A()` to `a = A` -- > then it gives same answer.Its happen because you try to allocate class a method but in `class A` no any other method so if you want same answer then at allocation time remove `()` – Virbhadrasinh Jun 29 '15 at 08:27

2 Answers2

1

why the outputs of des are different (one is 1 type(int), one is object type(Des)).

In the first case, you are print the instance of Des in the A class statement's body. At this point it's nothing else than an ordinary Python object - no descriptor protocol involved since you are not doing an attribute access on a class or instance, since the A class doesn't even exist yet - so you get the default representation of the Des object.

In the second case, you are looking up (attribute access) the name des on an instance of A. The attribute resolution mechanism (implemented in object.__getattribute__) finds the name des in A.__dict__ and finds out the associated object implements __get__, so it calls A.__dict__["des"].__get__(a, A) and returns the result - in this case A.dict["des"].num, which isint(1)`.

And the output of a.__dict__ and A.__dict__ is also different.

Yes of course. A.__dict__ is the dict of class A, a.__dict__ is the dict of instance a. Why would you expect same to share the same dict ?

What's the function of __get__(), and how to use it.

Martijn Pieters's links will answer this question.

Jacob Zimmerman
  • 1,521
  • 11
  • 20
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • thanks your answer , it help me a lot, and sovled most of my Confusion. – Arthur George Jun 29 '15 at 10:20
  • @ArthurGeorge then feel free to upvote and accept it. – bruno desthuilliers Jun 29 '15 at 10:28
  • thanks your answer , it help me a lot, and it solved most of my Confusion.But I still have some question. first how do the python interpreter know to call A.__dict__["des"].__get__(a, A). I think it will check if the associated object(Des) has implements the __get__ methond. Rigth?? – Arthur George Jun 29 '15 at 10:30
  • 1
    @ArthurGeorge you know you can edit your question don't you ? And yes, _as I already mentionned in my answer_, `object.__getattribute__()` (not "the python interpreter") will check if there's a _class_ attribute implementing `__get__ `, as documented here https://docs.python.org/2.7/reference/datamodel.html#invoking-descriptors – bruno desthuilliers Jun 29 '15 at 10:37
0

in your code the des is a class attribute and in a descriptor it(class attr) will call the get() ,in the next a.des calls the call() method so , thats the reason you got the different output (in your example output).