2

我对此处python 文档中的以下示例感到有些困惑。

>>> 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 is here 是在 Python 深处定义的实际 float 类。当我们调用 时float.__new__(cls, argument),我们偷偷地调用了返回给定参数的 float 实例的函数,但是我们传递给它的是 inch 类而不是 float 类。既然英寸类并没有真正做任何事情,为什么这会起作用?

4

2 回答 2

7

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

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

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

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

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

于 2012-11-23T19:16:54.470 回答
0

回答这个问题需要一点背景知识:

  1. 只能object.__new__()创建一种新instances类型的对象,这种对象不能被子类化。
  2. 实例具有type,可以在将类型名称 作为第一个参数传递cls给时分配。关键字创建了另一种对象:类(又名类型),这些对象 可以被子类化。__new__(cls)class

现在,回到你的例子,什么

float.__new__(cls, argument)

本质上是使用object.__new__(cls)创建一个新实例(float.__base__is object),为它分配类型clsinch在这种情况下),并且还使用argument定义的 in做一些事情float.__new__

因此,当clsis not floatbut时它会起作用也就不足为奇了inch:类/类型已经由 创建class inch(float),您只是将此类型分配给一个新实例。

于 2012-11-23T19:53:44.140 回答