15

How do I implement a method that overloads float(), i.e. it is called when an instance of a class I've written is passed to float()?

I am starting to write my own Fraction class:

class Fraction:
    def __init__(self, num = 0, denom = 1):
        self.num = float(num)
        self.denom = float(denom)

Now I want to be able to do this:

float(Fraction())

I tried using the below method, but that didn't work.

def float(self):
    return self.num / self.denom
Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
Yatharth Agarwal
  • 4,385
  • 2
  • 24
  • 53

1 Answers1

27

Define the __float__() special method on your class.

class MyClass(object):
    def __float__(self):
         return 0.0

float(MyClass())   # 0.0

Note that this method must return a float! The calculation self.num / self.denom, returns an int by default in versions of Python prior to 3.0 assuming both operands are integers. In this case you'd just make sure one of the operands is a float: float(self.num) / self.denom for example.

kindall
  • 178,883
  • 35
  • 278
  • 309
  • I _am_ using ints throughout my code for `self.num` and `self.denom`. 10x for the answer. – Yatharth Agarwal Apr 05 '12 at 19:31
  • What _would_ happen if you didn't return a float? – Yatharth Agarwal Apr 05 '12 at 19:32
  • 1
    You get a `TypeError` exception. – kindall Apr 05 '12 at 19:35
  • 1
    @YatharthROCK: Basically, you will create an unstable black hole inside your python interpreter and the universe will be destroyed. I think kindall is just pointing out the fact that `/` denotes integer division by default in <= python 2.x and floating point division in python 3.x. You should be aware of this. – Joel Cornett Apr 05 '12 at 19:38
  • 1
    @kindall: So when you call one of the special methods, it doesn't just execute the overloaded method, it still passes through the special method? – Joel Cornett Apr 05 '12 at 19:46
  • if you *are* using Python <3.0 , you can always use a future import to get float-returning division, i.e.: `from __future__ import division`. Then `self.num / self.denom` will work fine. – CrepeGoat Jan 04 '18 at 17:59