Skip to main content
 首页 » 编程设计

Python:当 cls 不是 float 时,为什么 float.__new__(cls) 可以工作

2025年05月04日18powertoolsteam

我对 python 文档中的以下示例感到有点困惑 here .

>>> class inch(float): 
...     "Convert from inch to meter" 
...     def __new__(cls, arg=0.0): 
...         return float.__new__(cls, arg*0.0254) 
... 
>>> print inch(12) 
0.3048 
>>>  

据推测,这里的 float 是在 Python 深处某处定义的实际 float 类。当我们调用 float.__new__(cls, argument) 时,我们偷偷调用了为给定参数返回 float 实例的函数,但我们将它传递给 inch 类而不是 float 类.既然 inch 类并没有真正做任何事情,为什么它会起作用呢?

请您参考如下方法:

因为inch 是float 的子类,它满足float.__new__() 实例工厂的所有要求。这是__new__(cls) static method的工作创建第一个参数的实例,而不是它的“自己”类的实例。

请注意此处的“静态方法”一词。 __new__ 工厂实际上只是出于继承原因而绑定(bind)到类的专用函数。换句话说,它是一个在面向对象的层次结构中发挥良好的功能。您应该通过 super() 找到它,或者直接调用它(如此处完成)。以下实际上会更像 pythonic:

def __new__(cls, arg=0.0): 
    return super(inch, cls).__new__(cls, arg*0.0254) 

因为如果 inch 被用于多重继承层次结构,那将调用“正确的”__new__ 函数;在这个简单的示例中,它最终会调用 float.__new__ 。

因此,__new__(cls, ...) 应该创建类型为 cls 的实例。那么为什么要把它绑定(bind)到一个类而不是让它成为一个更通用的函数呢?因为在 float.__new__(cls, value) 的情况下,它不仅创建了 cls 类型的新实例,还将其初始值设置为 value。为了让它工作,float.__new__(...) 需要深入了解 float 类的外观。因为 inch() 是 float() 的子类,所以它也具有成为 float() 的完全相同的必要位,因此当 float.__new__() 工厂创建一个新的 inch 实例时,所有这些位都会使它成为一个 inch() 实例。