Lost in descriptor land

Ian Kelly ian.g.kelly at gmail.com
Thu Jun 30 21:36:13 EDT 2016


On Thu, Jun 30, 2016 at 7:06 PM, Ankush Thakur
<ankush.thakur53 at gmail.com> wrote:
> Hello,
>
> There's something I don't understand about descriptors. On a StackOverflow discussion (http://stackoverflow.com/questions/12846116/python-descriptor-vs-property) one of the answers provides the following descriptors example:
>
> class Celsius( object ):
>     def __init__( self, value=0.0 ):
>         self.value= float(value)
>     def __get__( self, instance, owner ):
>         return self.value
>     def __set__( self, instance, value ):
>         self.value= float(value)
>
> class Temperature( object ):
>     celsius= Celsius()
>     farenheit= Farenheit()
>
> ... and then gets chided in the comments:
>
> "I believe your descriptor implementation of celsius is not correct. You should have set the celsius on instance rather than self; If you create two Temperature objects they will share the same celsius value."

That criticism is accurate. "self" above refers to the Celsius
instance, and there is only one Celsius instance for the Temperature
class, not one per Temperature instance.

> Overall, I have two problems:
> 1) I don't get the idea behind the 'instance' and 'owner' parameters at all. Is there some simple tutorial that can explain these?

First of all, do you understand what descriptors are? This is a fairly
advanced Python concept. For a general tutorial, I would point you to
https://docs.python.org/3/howto/descriptor.html

Whereas the self argument refers to the Celsius instance, the instance
argument refers to the instance of the object currently being accessed
through the descriptor protocol. That is, the object that the Celsius
descriptor is implementing a property of. Using the above example, if
I were to write:

    temp = Temperature()
    print(temp.celsius)

The access of temp.celsius will cause Celsius.__get__ to be called,
and the value of instance for that call will be temp

The owner argument is the class that this Celsius instance is a
descriptor of. Normally that is just type(instance); however it is
possible to invoke the __get__ method on the class object itself
rather than on an instance, in which case owner is (still) the class
object but instance is None.

> 2) I don't understand the motivation behind the comment. Of course declaring a class variable would cause celcius to be the same for all objects. Shouldn't we be instead using self.celcius in, say, __init__() and then everything will work fine?

It's not clear to me what alternative you're proposing. The reason
celsius is declared on the class is because it's a descriptor, and
descriptors implement properties of classes. Setting an instance
attribute to a descriptor won't accomplish anything.



More information about the Python-list mailing list