Reputation: 22294
When implementing a descriptor, it is possible to use __set_name__
to register under which attribute name the descriptor was set.
Although, suppose we were to set more than one attribute to the same descriptor, then there seems to be no way to know through which name the descriptor was accessed in the __get__
and __set__
method.
class Prop:
def __init__(self):
self._names = {}
def __set_name__(self, owner, name):
print(f'Attribute \'{name}\' was set to a Prop')
if owner in self._names:
self._names[owner].append(name)
else:
self._names[owner] = [name]
def __get__(self, instance, owner):
print(f'Prop was accessed through one of those: {self._names[owner]}')
prop = Prop()
class Foo:
bar = prop
baz = prop
foo = Foo()
foo.baz
Attribute 'bar' was set to a Prop
Attribute 'baz' was set to a Prop
Prop was accessed through one of those: ['bar', 'baz']
Is there a clean and general way to know from which attribute a descriptor was accessed?
Upvotes: 0
Views: 641
Reputation: 152637
Is there a clean and general way to know from which attribute a descriptor was accessed?
No, there is no clean and general way.
However if you want a dirty hack (please don't do that!) you can avoid the descriptor protocol and just pass in the name through which it was accessed manually:
class Descriptor:
def __get__(self, instance, owner, name=None):
print(f"Property was accessed through {name}")
return 'foo'
p = Descriptor()
class Test:
a = p
b = p
def __getattribute__(self, name):
for klass in type(self).__mro__:
if name in klass.__dict__ and isinstance(klass.__dict__[name], Descriptor):
return klass.__dict__[name].__get__(self, klass, name)
else:
return object.__getattribute__(self, name)
Upvotes: 2