Hello Ian, That seems like too much code involved. Is this how we do write inheritance in Python. Coming from Ruby and JS world I find Python inheritance mechanism confusing so far. :/
Thanks, Arup Rakshit a...@zeit.io > On 19-Mar-2019, at 9:32 PM, Ian Kelly <ian.g.ke...@gmail.com> wrote: > > Here's the thing: the result of calling super() is not an instance of the > base class. It's just a proxy object with a __getattribute__ implementation > that looks up class attributes in the base class, and knows how to pass > self to methods to simulate calling base class methods on an instance. This > works fine for looking up methods and property getters. It doesn't work so > well for simulating other behaviors, like setters, or comparisons, or > iteration, etc. > > A property is one example of what in Python is known as a descriptor, which > is described here: > https://docs.python.org/3/reference/datamodel.html#implementing-descriptors > > A settable property has a __set__ method per the descriptor protocol. When > you try to set an attribute with the name of the property, Python looks up > the name in the class dict, finds the property object, and then calls its > __set__ method. The class of the super proxy object, however, does not > contain this property, and because you're not doing an attribute lookup, > the super proxy's __getattribute__ does not get called. So all Python sees > is that you tried to set an attribute that doesn't exist on the proxy > object. > > The way I would suggest to get around this would be change your super() > call so that it looks up the property from the base class instead of trying > to set an attribute directly. For example, this should work: > > super(HeatedRefrigeratedShippingContainer, > self.__class__).celsius.fset(self, value) > > On Tue, Mar 19, 2019 at 9:12 AM Arup Rakshit <a...@zeit.io> wrote: > >> I have 3 classes which are connected to them through inheritance as you >> see in the below code: >> >> import iso6346 >> >> class ShippingContainer: >> """docstring for ShippingContainer""" >> >> HEIGHT_FT = 8.5 >> WIDTH_FT = 8.0 >> next_serial = 1337 >> >> @classmethod >> def _get_next_serial(cls): >> result = cls.next_serial >> cls.next_serial += 1 >> return result >> >> @staticmethod >> def _make_bic_code(owner_code, serial): >> return iso6346.create(owner_code=owner_code, >> serial=str(serial).zfill(6)) >> >> @classmethod >> def create_empty(cls, owner_code, length_ft, *args, **keyword_args): >> return cls(owner_code, length_ft, contents=None, *args, >> **keyword_args) >> >> # ... skipped >> >> def __init__(self, owner_code, length_ft, contents): >> self.contents = contents >> self.length_ft = length_ft >> self.bic = self._make_bic_code(owner_code=owner_code, >> >> serial=ShippingContainer._get_next_serial()) >> # ... skipped >> >> >> class RefrigeratedShippingContainer(ShippingContainer): >> MAX_CELSIUS = 4.0 >> FRIDGE_VOLUME_FT3 = 100 >> >> def __init__(self, owner_code, length_ft, contents, celsius): >> super().__init__(owner_code, length_ft, contents) >> self.celsius = celsius >> >> # ... skipped >> >> @staticmethod >> def _make_bic_code(owner_code, serial): >> return iso6346.create(owner_code=owner_code, >> serial=str(serial).zfill(6), >> category='R') >> @property >> def celsius(self): >> return self._celsius >> >> @celsius.setter >> def celsius(self, value): >> if value > RefrigeratedShippingContainer.MAX_CELSIUS: >> raise ValueError("Temperature too hot!") >> self._celsius = value >> >> # ... skipped >> >> >> class HeatedRefrigeratedShippingContainer(RefrigeratedShippingContainer): >> MIN_CELSIUS = -20.0 >> >> @RefrigeratedShippingContainer.celsius.setter >> def celsius(self, value): >> if value < HeatedRefrigeratedShippingContainer.MIN_CELSIUS: >> raise ValueError("Temperature too cold!") >> super().celsius = value >> >> >> >> >> Now when I run the code : >> >> Python 3.7.2 (v3.7.2:9a3ffc0492, Dec 24 2018, 02:44:43) >> [Clang 6.0 (clang-600.0.57)] on darwin >> Type "help", "copyright", "credits" or "license" for more information. >>>>> from shipping import * >>> h1 = >> HeatedRefrigeratedShippingContainer.create_empty('YML', length_ft=40, >> celsius=-18) >> Traceback (most recent call last): >> File "<stdin>", line 1, in <module> >> File "/Users/aruprakshit/python_playground/shipping.py", line 23, in >> create_empty >> return cls(owner_code, length_ft, contents=None, *args, **keyword_args) >> File "/Users/aruprakshit/python_playground/shipping.py", line 47, in >> __init__ >> self.celsius = celsius >> File "/Users/aruprakshit/python_playground/shipping.py", line 92, in >> celsius >> super().celsius = value >> AttributeError: 'super' object has no attribute 'celsius' >>>>> >> >> >> Why here super is denying the fact that it has no celsius setter, although >> it has. While this code doesn’t work how can I solve this. The thing I am >> trying here not to duplicate the validation of temperature which is already >> in the setter property of the RefrigeratedShippingContainer class. >> >> >> >> >> Thanks, >> >> Arup Rakshit >> a...@zeit.io >> >> >> >> -- >> https://mail.python.org/mailman/listinfo/python-list >> > -- > https://mail.python.org/mailman/listinfo/python-list -- https://mail.python.org/mailman/listinfo/python-list