为什么不在python中__new__而不是__new__和__init__?

时间:2014-02-05 01:37:12

标签: python

假设以下代码:

class NumStorage(object):

    def __new__(cls, *nargs):
        name = cls.__name__
        parents = cls.__bases__
        kwargs = {'num%i' % pos : i for pos, i in enumerate(nargs, 1)}
        if any(kwargs.values()) and len(kwargs.values()) >= 2:
            end = len(kwargs.values()) + 1
            kwargs['num%i' % end] = sum(kwargs.values())
        self = type(name, parents, kwargs)
        return self

NumStorage对象接收任意数量的数字,如果有两个或更多数字且它们的总和加起来大于0,则会创建一个新的kwarg键。 / p>

如果NumStorage实例的初始化可以在__new__中进行,那么为什么python甚至需要一个__init__?另一件令我困惑的事情;如果我们确实向__init__类添加NumStorage方法,那么:

class NumStorage(object):

    def __new__(cls, *nargs):
        name = cls.__name__
        parents = cls.__bases__
        kwargs = {'num%i' % pos : i for pos, i in enumerate(nargs, 1)}
        if any(kwargs.values()) and len(kwargs.values()) >= 2:
            end = len(kwargs.values()) + 1
            kwargs['num%i' % end] = sum(kwargs.values())
        self = type(name, parents, kwargs)
        return self

    def __init__(self, *nargs):
        print("initializing")

它永远不会打印“初始化”,即使__init__应该在__new__之后调用,因为__new__返回了一个对象的实例,不是吗?如果不是,我对此感到困惑是什么?

2 个答案:

答案 0 :(得分:3)

__init__排在第一位。 __new__主要添加到......好吧,我会让documentation解释一下:

  

__new__()主要用于允许不可变类型的子类(如int,str或tuple)自定义实例创建。它也通常在自定义元类中重写,以自定义类创建。

__init__对于旧式的课程系统来说已经足够好了。即使你将一个“不可变的”旧式类子类化,你也只需要为超类的__init__提供适当的参数。这并没有削减它的子类,比如tuple

至于__init__未被调用:

  

如果__new__()返回 cls 的实例,则返回新实例   __init__()方法将像__init__(self[, ...])一样被调用,其中 self 是新实例,其余参数与   被传递给__new__()

     

如果__new__()未返回 cls 的实例,则为新的   

。实例的__init__()方法不会被调用。

答案 1 :(得分:1)

  

python甚至需要一个__init__

不,python不需要 __init__,但如果只有__new__,那么每次创建一个类时,你都需要弄清楚所有的进入__new__的点点滴滴。

它使python更容易,并且更不容易出错,将两者分开。

另外,历史上__init__位于__new__之前。