我对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类。由于英制等级并没有真正做任何事情,为什么这样做呢?
答案 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)
回答这个问题需要一些背景知识:
object.__new__()
才能创建新的instances
类型的对象
种类的对象不能被子类化。type
,可在传递类型名称时进行分配
cls
到__new__(cls)
作为第一个参数。 class
个关键字创建者
另一种对象:类(a.k.a类型)和这些类型的对象
可以进行子类化。现在,回到你的例子,
float.__new__(cls, argument)
本质上是使用object.__new__(cls)
创建新实例(float.__base__
是object
),
将cls
类型(在这种情况下为inch
)分配给它,并对argument
中定义的float.__new__
执行某些操作。
因此,当cls
不是float
而inch
时,它会工作并不奇怪:{/ 1}}已经创建了类/类型,你是只需将此类型分配给新实例。