Skip to main content
2 of 2
added 74 characters in body

Python - Temperature - descriptors with conversion

So I'm trying to understand the concept of descriptors and gathered some code together and made an exampel out of different sources. Like the offical documentation and StackOverflow answers. I'd hope someone can me tell some tricks about this concept or how to make this code better in general. Thanks in advanced.

PS: If someon could tell me why celsius needs to be 9_007_199_254_740_991 + 1 higher instead of just * += 1 * would be nice to know.

from abc import ABC

class Validator(ABC):
    
    def __set_name__(self,owner,name):
        self.private_name = '_' + name

    def __get__(self,obj,objtype=None):
        return getattr(obj,self.private_name)
    def __set__(self,obj,value):
        self.validate(obj,value)
        rval = round(value,3)
        setattr(obj,self.private_name,rval)
        return obj._notify(self.private_name.replace('_',''))

    def validate(self,obj,value):
        if not isinstance(value, (int, float)):
            raise TypeError(f'Expected {value!r} to be an int or float')
        if self.minvalue is not None and value < self.minvalue:
            raise ValueError(
                f'Expected {value!r} to be at least {self.minvalue!r}'
            )
        if self.maxvalue is not None and value > self.maxvalue:
            raise ValueError(
                f'Expected {value!r} to be no more than {self.maxvalue!r}'
            )

class Celsius(Validator):
    minvalue = -273.150 #Absolute zero
    maxvalue = 1.42*pow(10,32) #Planck temperature

class Farenheit(Validator):
    minvalue = -459.670 #Absolute zero
    maxvalue = 2.55*pow(10,32) #Planck temperature

class Kelvin(Validator):
    minvalue = 0 #Absolute zero
    maxvalue = 1.417*pow(10,32) #Planck temperature

class Temperature( object ):
    celsius= Celsius()
    farenheit= Farenheit()
    kelvin = Kelvin()
    def __init__(self,typ='celsius',val=0.0):
        setattr(self,typ,val)

    def _notify(self,changed_by):
        lst = ['celsius','farenheit','kelvin']
        lst.remove(changed_by)
        val = getattr(self,changed_by)
        for i in lst:
            con = getattr(Temperature,f'convert_{changed_by}_to_{i}')(val)
            rcon= round(con,3)
            setattr(self,'_'+i,rcon)
    
    @staticmethod
    def convert_kelvin_to_celsius(kelvin) -> celsius:
        return kelvin-273.15
    @staticmethod
    def convert_celsius_to_kelvin(celsius) -> kelvin:
        return celsius+273.15
    @staticmethod
    def convert_celsius_to_farenheit(celsius) -> farenheit:
        return celsius*1.8+32
    @staticmethod
    def convert_kelvin_to_farenheit(kelvin) -> farenheit:
        return kelvin*1.8-459.67
    @staticmethod
    def convert_farenheit_to_kelvin(farenheit) -> kelvin:
        return (farenheit+459.67)*1.8
    @staticmethod
    def convert_farenheit_to_celsius(farenheit) -> celsius:
        return (farenheit-32)*1.8

if __name__ == '__main__':
    t = Temperature(typ='celsius',val=0.0)
    print(t.kelvin,t.farenheit)
    t.celsius = -273.15
    print(t.kelvin,t.farenheit)
    t.celsius = 1.42*pow(10,32)
    print(t.kelvin,t.farenheit)
    t.celsius += 9_007_199_254_740_991 #+ 1

Output

273.15 32.0
0.0 -459.67
1.42e+32 2.556e+32