Python:当cls不浮动时,为什么会浮动.__ new __(cls)工作?

时间:2012-11-23 18:54:58

标签: python

我对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类。由于英制等级并没有真正做任何事情,为什么这样做呢?

2 个答案:

答案 0 :(得分:6)

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

请注意“静态方法”这个词。 __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)的情况下,它不仅会创建类型为cls的新实例,还会将其初始值设置为value。为了使其发挥作用,float.__new__(...)需要对float类的内容有深入的了解。因为inch()float()的子类,所以它具有完全相同的必要位也是float(),因此当float.__new__()工厂创建新的inch时实例,所有这些位都是为了使它成为inch()实例。

答案 1 :(得分:0)

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

  1. 只有object.__new__()才能创建新的instances类型的对象 种类的对象不能被子类化。
  2. 实例具有type,可在传递类型名称时进行分配 cls__new__(cls)作为第一个参数。 class个关键字创建者 另一种对象:类(a.k.a类型)和这些类型的对象 可以进行子类化。
  3. 现在,回到你的例子,

    float.__new__(cls, argument)
    

    本质上是使用object.__new__(cls)创建新实例(float.__base__object), 将cls类型(在这种情况下为inch)分配给它,并对argument中定义的float.__new__执行某些操作。

    因此,当cls不是floatinch时,它会工作并不奇怪:{/ 1}}已经创建了类/类型,你是只需将此类型分配给新实例。