Reputation: 7729
A python descriptor that I'm working with is sharing its value across all instances of its owner class. How can I make each instance's descriptor contain its own internal values?
class Desc(object):
def __init__(self, initval=None,name='val'):
self.val = initval
self.name = name
def __get__(self,obj,objtype):
return self.val
def __set__(self,obj,val):
self.val = val
def __delete__(self,obj):
pass
class MyClass(object):
desc = Desc(10,'varx')
if __name__ == "__main__":
c = MyClass()
c.desc = 'max'
d = MyClass()
d.desc = 'sally'
print(c.desc)
print(d.desc)
The output is this, the last call set the value for both objects:
localhost $ python descriptor_testing.py
sally
sally
Upvotes: 3
Views: 967
Reputation: 19769
There is only one descriptor object, stored on the class object, so self
is always the same. If you want to store data per-object and access it through the descriptor, you either have to store the data on each object (probably the better idea) or in some data-structure keyed by each object (an idea I don't like as much).
I would save data on the instance object:
class Desc(object):
default_value = 10
def __init__(self, name):
self.name = name
def __get__(self,obj,objtype):
return obj.__dict__.get(self.name, self.default_value)
# alternatively the following; but won't work with shadowing:
#return getattr(obj, self.name, self.default_value)
def __set__(self,obj,val):
obj.__dict__[self.name] = val
# alternatively the following; but won't work with shadowing:
#setattr(obj, self.name, val)
def __delete__(self,obj):
pass
class MyClass(object):
desc = Desc('varx')
In this case, the data will be stored in the obj
's 'varx' entry in its __dict__
. Because of how data descriptor lookup works though, you can "shadow" the storage location with the descriptor:
class MyClass(object):
varx = Desc('varx')
In this case, when you do the lookup:
MyClass().varx
The descriptor object gets called and can do its lookup, but when the lookup goes like this:
MyClass().__dict__['varx']
The value is returned directly. Thus the descriptor is able to store its data in a 'hidden' place, so to speak.
Upvotes: 7