Python:float的子类可以在其构造函数中获取额外的参数吗?

问题描述 投票:9回答:4

在Python 3.4中,我想创建一个float的子类 - 可以在数学和布尔运算中使用,如float,但具有其他自定义功能,并且可以在初始化时接收控制该功能的参数。 (具体来说,我想要一个自定义的__str__和该方法中使用的参数。)

但是,我似乎无法获得float的子类来拥有一个功能性的双参数构造函数。为什么?这仅仅是扩展内置类型的限制吗?

例:

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

现在,如果我尝试Foo(1,2)我得到:

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

令人惊讶的是,我的新__init__的论点也被强制执行,所以如果我做Foo(1)我得到:

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

这是什么交易?我用list的子类型做了类似的事情,并且惊讶它在float上没有用。

python python-3.x types subclass built-in
4个回答
10
投票

由于float是不可变的,你也必须覆盖__new__。以下应该做你想要的:

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

另见Sub-classing float type in Python, fails to catch exception in __init__()


4
投票

@cgogolin和@qvpham都提供了工作答案。但是,我认为float.__init__(value)方法中的__init__Foo的初始化无关。也就是说,它无法初始化Foo的属性。因此,它会导致对子类化float类型的操作的必要性产生混淆。

实际上,解决方案可以进一步简化如下:

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

3
投票

cgogolin的解决方案是正确的。它就像使用另一个不可变的类,如int,str,...但我会写:

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

0
投票

您可以在不实施__init__的情况下执行此操作:

class Foo(float):
    def __new__(cls, value, extra):
        instance = super().__new__(cls, value)
        instance.extra = extra
        return instance

正在使用:

>>> foo = Foo(1, 2)
>>> print(foo)
1.0
>>> print(foo.extra)
2
© www.soinside.com 2019 - 2024. All rights reserved.