What is the usage of third argument objtype in Python descriptor's __get__ [duplicate]
Asked Answered
W

2

10

I know that in Python we have to supply __get__ function when implementing a descriptor. The interface is like:

def __get__(self, obj, objtype=None):
    pass

My question is:

Why we have to supply objtype arg? What is objtype used for?

I did not see some examples about the usage of this arg.

Winni answered 25/5, 2015 at 8:34 Comment(4)
The documentation of object.__get__ does not mention objtype. Where did you read about it?Acridine
@LutzHorn owner is objtype in this case, i.e the class.Zadazadack
intermediatepythonista.com/classes-and-objects-ii-descriptorsMurrain
Part of your confusion is that you have the function prototype wrong. According to the docs linked by Lutz Horn, owner (not objtype, as already pointed out) does not default to None in any version of Python.Pend
Z
3

It gives users an option to do something with the class that was used to call the descriptor.

In normal cases when the descriptor is called through the instance we can get the object type by calling type(ins).

But when it is called through the class ins will be Noneand we won't be able to access the class object if the third argument was not present.


Take functions in Python for example, each function is an instance of types.FunctionType and has a __get__ method that can be used to make that function a bound or unbound method.

>>> from types import FunctionType
>>> class A(object):
    pass
...
>>> def func(self):
    print self
...
>>> ins = A()
>>> types.FunctionType.__get__(func, ins, A)() # instance passed
<__main__.A object at 0x10f07a150>
>>> types.FunctionType.__get__(func, None, A)  # instance not passed
<unbound method A.func>
>>> types.FunctionType.__get__(func, None, A)()
Traceback (most recent call last):
  File "<ipython-input-211-d02d994cdf6b>", line 1, in <module>
    types.FunctionType.__get__(func, None, A)()
TypeError: unbound method func() must be called with A instance as first argument (got nothing instead)
>>> types.FunctionType.__get__(func, None, A)(A())
<__main__.A object at 0x10df1f6d0>
Zadazadack answered 25/5, 2015 at 9:48 Comment(3)
If it is useful for __get__, why is the owner parameter absent from __set__ and __delete__ as well?Columelliform
@Maggyero Any usecases you could think of having owner or objtype in __set__ and __delete__, when they are called from class not instance?Zadazadack
An application I can think of is managing access to class attributes (similar to managing access to instance attributes), where A.x would look up A._x (already possible thanks to the owner parameter), A.x = 'foo' would update A._x (not currently possible) and del A.x would delete A._x (not currently possible).Columelliform
A
0

From the documentation of object.__get__(self, instance, owner):

owner is always the owner class, while instance is the instance that the attribute was accessed through, or None when the attribute is accessed through the owner.

So you don't supply owner, it is set depending on how __get__ is called.

Acridine answered 25/5, 2015 at 8:52 Comment(1)
Do you know some circumstance where owner is used? I just don't know the purpose of this arg.Winni

© 2022 - 2024 — McMap. All rights reserved.