-3

I'm trying to solve a problem using python Descriptors.. Code is as below

class Celsius( object ):
    def __init__( self, value=0.0 ):
        self.value= float(value)
    def __get__( self, instance, owner ):
        return float(self.value)
    def __set__( self, instance, value ):
        self.value= float(value)

class Fahrenheit( object ):
    def __get__( self, instance, owner ):
        return (instance.celsius * 9 / 5 + 32.0)
    def __set__( self, instance, value ):
        instance.celsius= (float(value)-32.0) * 5 / 9

class Temperature( object ):
    def __init__(self, fahrenheit):
        self.fahrenheit = fahrenheit

    fahrenheit = Fahrenheit()
    celsius = Celsius()

t1 = Temperature(32)
print(t1.fahrenheit, t1.celsius)
t1.celsius = 0
print(t1.fahrenheit, t1.celsius)

Expected O/P is

32 0.0
32.0 0.0

But I get

32.0 0.0
32.0 0.0

Please help where should I change or if there is any other better way.

r.ook
  • 13,466
  • 2
  • 22
  • 39
Prashy
  • 61
  • 6
  • 2
    They both return `float`s, why would you expect an `int` there? – r.ook Feb 20 '19 at 20:53
  • Possible duplicate of [Understanding \_\_get\_\_ and \_\_set\_\_ and Python descriptors](https://stackoverflow.com/questions/3798835/understanding-get-and-set-and-python-descriptors) – r.ook Feb 20 '19 at 20:54
  • The output you say you're getting is what I'd expect from your code. Why do you think you should get `32` from `t1.fahrenheit` when you first access it? Also, that descriptor design is very weird, as every instance of `Temperature` will share the same temperature values (since they live in the `Celsius` descriptor instance). It would be much more natural to save the underlying value in the instance somewhere. – Blckknght Feb 20 '19 at 21:00
  • I need to get the O/P as 32 0.0 32.0 0.0 . I'm trying to figure out how to do it – Prashy Feb 20 '19 at 21:05
  • I'm looking for what to change in my code to get the desired O/P – Prashy Feb 20 '19 at 21:21
  • Please Explain why you want (and expect) no decimal portion to print on the first number output. – CryptoFool Feb 20 '19 at 21:38
  • its a part of python learning exercise I'm trying to solve.. – Prashy Feb 20 '19 at 21:57
  • Frankly, it sounds like your exercise is bugged. – Blckknght Feb 20 '19 at 21:58
  • Is there a better way to write the code to get the expected O/P (without editing the print statement).. I am new comer to python and trying learn by googling and posting questions.. – Prashy Feb 20 '19 at 22:04

3 Answers3

0

With no explanation of why you want the output you desire...just that you WANT that output, you can get it by changing the last four lines of your code to:

t1 = Temperature(32)
print(int(t1.fahrenheit), t1.celsius)
t1.celsius = 0
print(t1.fahrenheit, t1.celsius)

Output:

32 0.0
32.0 0.0

I assume you want something other than this, but I can't figure out what you might want. The output you're getting from your code as is is perfectly reasonable.

CryptoFool
  • 21,719
  • 5
  • 26
  • 44
0

class Celsius: def get(self, instance, owner): return 5 * (instance.fahrenheit - 32) /9

def __set__(self, instance, value):
    instance.fahrenheit = 32 + 9 * value/5

class Temperature: celsius = Celsius()

def __init__(self, initial_f):
    self.fahrenheit = initial_f
Prashy
  • 61
  • 6
0

The problem is that when you assign something to fahrenheit, the __set__() method of Fahrenheit delegates to instance.celsius. All of the methods on Celsius convert to float. If you want your examples to work as you expect, you'll need Celsius to delegate to instance.fahrenheit instead while still doing it's float conversions, maybe only only in __get__() if that's what you want.

So, to sum up, store in Fahrenheit type without type conversion, and delegate to Fahrenheit from Celsius.

As some others have noted, your descriptor design makes it so that all instances of Temperature will store the same value. If you want different instances to hold different values, you'll need to save the value either directly on the instance under a different name (typically, it would be _fahrenheit in this situation) or in a kind of dictionary where the key is instance.

Lastly, for this kind of situation where there's a value shared between two descriptors and they're not likely to be reused somewhere else, I would go the property route.

Jacob Zimmerman
  • 1,521
  • 11
  • 20