Search code examples
pythonclassinheritancepropertiessubclass

Python Class update parent variables by subclass


With my limited understanding of @property,@setter, and @getter, I came up with following code.

class BitCounts:
    sign_bit = 0
    exponent_bits = 0
    mantissa_bits = 0
    _total_bits = 0

    @property
    def total_bits(self):
        return self._total_bits

    @total_bits.setter
    def total_bits(self):
        self._total_bits = self.sign_bit + self.exponent_bits + self.mantissa_bits


class Single(BitCounts):
    sign_bit = 1
    offset = 0x7F
    exponent_bits = 8
    mantissa_bits = 23
    _total_bits = BitCounts.total_bits


class Double(BitCounts):
    sign_bit = 1
    offset = 0x400
    exponent_bits = 11
    mantissa_bits = 52
    _total_bits = BitCounts.total_bits

My intention is to use the subclass Single and Double in other functions as a set of options like so, for example:

    def some_function(option=Single):
        print("exponent bit counts are: %d", option.exponent_bits)
        print("mantissa bit counts are: %d", option.mantissa_bits)
        print("total bit counts are: %d", option.total_bits)

I would like total_bits to be automatically recalculated using values from subclass Single or Double.

I am trying to avoid extra functions to perform the calculation at subclass level.

With above codes, by calling Single.total_bits, or Double.total_bits, I am only getting a message saying <property object at 0x000002258DF7CB30>, what did I do wrong, and how can I fix it?


Solution

  • The way you are using subclasses with hard-coded static values suggests these should be instances not subclasses. This is also suggested by your temptation to use self even though you haven't made any instances. self refers to a particular instance.

    Also, setters typically take a value as an argument. You don't have that in your setter because total_bits is completely dependent on other values. As such you should just move your setter calculation to the getter and return the result of the calculation.

    Consider:

    class BitCounts:
        def __init__(self, sign,offset, exponent, mantissa):       
            self.sign_bit = sign
            self.offset = offset
            self.exponent_bits = exponent
            self.mantissa_bits = mantissa
    
        @property
        def total_bits(self):
            return self.sign_bit + self.exponent_bits + self.mantissa_bits
    
    # now make two instances:
    single = BitCounts(1, 0x7F, 8, 23 )
    double = BitCounts(1, 0x400, 11, 52)
    
    print(single.total_bits)
    # 32
    
    print(double.total_bits)
    # 64