When I make the "data" variable a class variable, the following works, but when I make it an object variable, the descriptor is not called. Please help.
class Data(object):
products = {
'milk': {'price': 1.50, 'quantity': 10},
'eggs': {'price': 0.20, 'quantity': 100},
'cheese': {'price': 2.00, 'quantity': 10}
}
def __get__(self, obj, klas):
print "Here in descriptor"
return self.products
class BusinessLogic(object):
def __init__(self): # When I remove these 2 lines
self.data = Data()
#data = Data() # and enable this line it does work !
def main():
b = BusinessLogic()
b.data
if __name__ == '__main__':
main()
That's because descriptors should only be defined as class attributes, not instance attributes:
From docs:
The following methods only apply when an instance of the class containing the method (a so-called descriptor class) appears in an owner class (the descriptor must be in either the owner’s class dictionary or in the class dictionary for one of its parents).
To make descriptor work with instance attributes as well you need to override the __getattribute__
method of BusinessLogic
.(Haven't tested this thoroughly, but works fine for your case):
def __getattribute__(self, attr):
obj = object.__getattribute__(self, attr)
if hasattr(obj, '__get__'):
return obj.__get__(self, type(self))
return obj
In case you've a data descriptor then you need to handle the __setattr__
part as well.
def __setattr__(self, attr, val):
try:
obj = object.__getattribute__(self, attr)
except AttributeError:
# This will be raised if we are setting the attribute for the first time
# i.e inside `__init__` in your case.
object.__setattr__(self, attr, val)
else:
if hasattr(obj, '__set__'):
obj.__set__(self, val)
else:
object.__setattr__(self, attr, val)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With