Search code examples
pythonpython-3.xtypessubclassbuilt-in

Python: Can a subclass of float take extra arguments in its constructor?


In Python 3.4, I'd like to create a subclass of float -- something that can be used in math and boolean operations like a float, but has other custom functionality and can receive an argument at initialization that controls that functionality. (Specifically, I wanted to have a custom __str__ and a parameter that is used in that method.)

However, I can't seem to get a subclass of float to have a functional two-argument constructor. Why? Is this simply a limitation on extending built-in types?

Example:

class Foo(float):
    def __init__(self, value, extra):
        super().__init__(value)
        self.extra = extra

Now if I try Foo(1,2) I get:

TypeError: float() takes at most 1 argument (2 given)

Surprisingly, my new __init__'s arguments are enforced too, so if I do Foo(1) I get:

TypeError: __init__() missing 1 required positional argument: 'extra'

What's the deal here? I've done similar things with subtypes of list and was surprised it didn't work on float.


Solution

  • As float is immutable you have to overwrite __new__ as well. The following should do what you want:

    class Foo(float):
        def __new__(self, value, extra):
            return float.__new__(self, value)
        def __init__(self, value, extra):
            float.__init__(value)
            self.extra = extra
    
    foo = Foo(1,2)
    print(str(foo))
    1.0
    print(str(foo.extra))
    2
    

    See also Sub-classing float type in Python, fails to catch exception in __init__()