How to resolve Attribute error in Python?

521 Views Asked by At

I am learning Descriptors in python. I am trying the code , but getting below mentioned Attribute error.

AttributeError: 'celciusDescriptor' object has no attribute '_celciusDescriptor__fahrenheit'

I am trying to get the output as (32,0) which is (Fahrenheit, celcius), by getting the temperature in Fahrenheit.

'''

  class celciusDescriptor:
        def __get__(self, obj, owner):
            tempc = self.__fahrenheit
            celcius = (tempc - 32)*(5/9)
            return self.celcius
        def __set__(self, obj, value):
            tempcelc = (value - 32)*(5/9)
            return tempcelc
    
           
    class Temperature:
        celcius = celciusDescriptor()
        def __init__(self, fahrenheit):
            self.fahrenheit = fahrenheit
            
    
    t1 = Temperature(32)
    t1.fahrenheit
    t1.celcius

'''

2

There are 2 best solutions below

2
On

Here is one pattern for doing this (by the way, class names typically start with upper case). There is only a need to keep a Celsius or a Fahrenheit value as one can be computed from the other. In this case I am using a class CelsiusDescriptor to keep the Celsius value (even though you construct a Temperature instance with a Fahrenheit value), since this is the way you have it. I then use ordinary properties for getting and setting the Fahrenheit value. The actual Celsius value is stored in the Temperature object's internal __dict__ attribute, where its other attributes are normally stored. This descriptor also does type enforcement.

class CelsiusDescriptor:
    def __init__(self, name):
        self.name = name

    def __get__(self, instance, cls):
        if instance is None:
            return self
        else:
            return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, (int, float)):
            raise TypeError('Expected an int or a float')
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        del instance.__dict__[self.name]


class Temperature:
    celsius = CelsiusDescriptor('celsius') # a class attribute

    def __init__(self, fahrenheit):
        self.celsius = (fahrenheit-32) * 5/9;

    @property
    def fahrenheit(self):
        return self.celsius*9/5 + 32

    @fahrenheit.setter
    def fahrenheit(self, fahrenheit):
        self.celsius = (fahrenheit-32) * 5/9;

t = Temperature(32)
print(t.fahrenheit, t.celsius)
t.celsius = 100
print(t.fahrenheit, t.celsius)
t.fahrenheit = -40
print(t.fahrenheit, t.celsius)

Prints:

32.0 0.0
212.0 100
-40.0 -40.0
1
On

Try this:

class celciusDescriptor:
        def __get__(self, tempc):
            tempc = None
            self.celcius = (tempc - 32)*(5/9)
            print(self.celcius)
        def __set__(self, value):
            tempcelc = (value - 32)*(5/9)
            print(tempcelc)
    
           
class Temperature:
        celcius = celciusDescriptor()
        def __init__(self, fahrenheit):
            self.fahrenheit = fahrenheit
            print(self.fahrenheit)
            
    
t1 = Temperature(32)