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
.
Both @cgogolin and @qvpham provide working answers. However, I reckon that float.__init__(value)
within the __init__
method is irrelevant to the initialization of Foo
. That is, it does nothing to initialize attributes of Foo
. As such, it rather causes confusion on the necessity of the operation toward subclassing the float
type.
Indeed, the solution can be further simplified as follows:
In [1]: class Foo(float):
...: def __new__(cls, value, extra):
...: return super().__new__(cls, value)
...: def __init__(self, value, extra):
...: self.extra = extra
In [2]: foo = Foo(1,2)
...: print(str(foo))
1.0
In [3]: print(foo.extra)
2
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__()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With