ng.newbie
ng.newbie

Reputation: 3218

What is the purpose of instance and owner in Python descriptors?

I am trying to understand descriptors in Python. What I can't seem to get my head around is what is the instance and owner in the descriptor method:

object.__get__(self, instance, owner)

Now I have read the documentation saying that:

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.

Unfortuanately I am having trouble understanding what that means. Does owner refer to the class itself? The class object? Then what is the purpose of instance being passed to it?

Upvotes: 4

Views: 2248

Answers (3)

Rohit
Rohit

Reputation: 4158

Consider this

 __get__(self, instance, owner):

owner - this refers to the class where the descriptor object was created, remember descriptor objects are defined at class level.

instance - this refers to the object of the class owner where you defined the descriptor object.

The purpose of passing the instance to the __get__ method of the descriptor is to make sure we know and identify from which object of the owner class you are accessing the descriptor instance.

Since descriptor objects are created at the class level, so a naive implementation of the descriptor class itself can result in having multiple objects of the owner class overriding the value of descriptor instance. Here is an example of such code

def __get__(self, instance, owner):
    return self.data

def __set__(self, instance, data):
    if value < 1:
        raise Exception("Negative or zero is not allowed")
    else:
        self.data = value

So in the above example the value of data is stored inside the descriptor instance only and this code will have serious side effects, if you are creating multiple objects of the owner class and let's say these objects are setting the value of data.

So in order to solve such a problem you would need to store the value of data in __dict__ of instance but how would you that if you don't have access to instance in the descriptor class itself ?? So as per my experience this is the primary purpose of having instance in the descriptor class. As a reference for solving the above mentioned problem and putting the instance in use, here is the code

class DataDescriptor(object):
    def __init__(self, attribute):
        self.default = 100
        self.attribute = attribute

    def __get__(self, instance, owner):
        print('Getting the value of', self.attribute,
              '__get__ of Data descriptor invoked')
        return instance.__dict__.get(self.attribute, self.default)

    def __set__(self, instance, value=200):
        if value > 0:
            print('__set__ of Data descriptor invoked')
            instance.__dict__[self.attribute] = value
        else:
            sys.exit('Negative value not allowed')

Upvotes: 1

panda-34
panda-34

Reputation: 4209

The relationships can be illustrated by this code:

class DescriptorClass:
    def __get__(self, instance, owner):
        return self, instance, owner

class OwnerClass:
    descr = DescriptorClass()

ownerinstance = OwnerClass()

self, instance, owner = ownerinstance.descr

assert self is OwnerClass.__dict__['descr']
assert instance is ownerinstance
assert owner is OwnerClass

self, instance, owner = OwnerClass.descr
assert instance is None

Upvotes: 4

bruno desthuilliers
bruno desthuilliers

Reputation: 77892

Does owner refer to the class itself?

Yes.

The class object?

This is the exact same thing.

Then what is the purpose of instance being passed to it?

How would the descriptor access the instance it's been looked up on else ? If you take the builtin property type for example, it works by storing accessor functions and calling back on those functions. Those functions expect the current instance as first argument (canonically named "self"). If the descriptor doesn't get the current instance, it obviously cannot pass it to the accessor.

Upvotes: 2

Related Questions