0

With this code I want to build a new Energy class that makes use of the existing mathematical operations (data model methods) in the build in float class.

class Energy(float):
    def __init__(self, value, unit="J"):
        super().__init__(value)
        
        # dict of possible energy input units
        self.units= {
            "J" : 1.0,
            "kJ": 10**-3,
            "kcal" : 1/(4.1868) * 10**-3
        }
        
        # check wich unit is used and calculate the value into 'J'
        for e in self.units.keys():
            if e == unit:
                self = value * self.units[e]
    
    def kJ(self):
        return self * self.unit["kJ"]
    
    def kcal(self):
        return self * self.unit["kcal"]
    
    def __str__(self):
        return str(float(self)) + " J"
    
e = Energy(10, "kJ")
print(e)

This can't be achieved, so I followed the suggested solution by Tim Roberts. This means to implement all of the data model methods like __add__() etc. by your self.

perperam
  • 432
  • 3
  • 10
  • `self = value * self.units[e]` does nothing. Well, it bind a new value to the local name `self`, but that has no effect outside the function. You cannot change `self` -- floats are immutable. You may need to implement this using encapsulation rather than inheritance. – Tim Roberts Aug 27 '22 at 23:26
  • Also, if you are multiplying by `units` on the way in to get `J`, then you need to divide in your `kJ` function, or vice versa. – Tim Roberts Aug 27 '22 at 23:30
  • The `TypeError` you are seeing is actually because `float` is immutable. This means that `__new__` should be overwritten in stead of `__init__`. See also this question: https://stackoverflow.com/questions/73433246/python-primitive-class-constructor-int-cant-convert-non-string-with-explici/73433359#73433359 – kolokkol Aug 27 '22 at 23:44

1 Answers1

0

Here is a start on an encapsulation solution. Yes, you will have to implement all of the special methods (like __add__, __sub__, etc) rather than inheriting them, but that's only a bit tedious at the very start. That would let you handle either floats or other Energy objects.

class Energy:
    # Conversions.
    units= {
        "J" : 1.0,
        "kJ": 10**-3,
        "kcal" : 1/(4.1868) * 10**-3
    }

    def __init__(self, value, unit="J"):
        self.value = value * self.units[unit]
    
    def kJ(self):
        return self.value / self.unit["kJ"]
    
    def kcal(self):
        return self.value / self.unit["kcal"]
    
    def __str__(self):
        return str(self.value) + " J"
    
e = Energy(10, "kJ")
print(e)
Tim Roberts
  • 48,973
  • 4
  • 21
  • 30