【问题标题】:Why not just __new__ and not __new__ and __init__ in python?为什么不只是 __new__ 而不是 __new__ 和 __init__ 在 python 中?
【发布时间】:2014-03-01 06:47:50
【问题描述】:

假设以下代码:

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 键。

如果 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__ 返回了对象的一个​​实例,不是吗?如果不是,我对什么感到困惑?

【问题讨论】:

标签: python


【解决方案1】:

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

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

__init__ 对于老式的类系统来说已经足够好了。即使你继承了一个“不可变”的旧式类,你也只需为超类的__init__ 提供适当的参数。这并不能用tuple 的子类来削减它。

至于__init__不被调用:

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

如果 __new__() 没有返回 cls 的实例,那么新的 不会调用实例的__init__() 方法。

【讨论】:

  • 那我该如何编辑上面的代码,让__new__返回一个类NumStorage的实例,因为我认为使用类型是这样做的?
  • @user3002473:您对type 所做的是创建并返回一个新类。相反,您需要做的是调用super(NumStorage, cls).__new__(cls, *nargs),然后执行初始化对象所需的任何操作。
  • 啊,这很有意义。非常感谢!
【解决方案2】:

python甚至需要__init__吗?

不,python 不需要__init__,但如果只有__new__,那么每次创建类时,都需要弄清楚进入__new__

这使得 python 更容易,更不容易出错,将两者分开。

另外,从历史上看,__init____new__ 之前。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-09
    • 2016-05-28
    • 1970-01-01
    • 2010-10-15
    • 2011-06-19
    相关资源
    最近更新 更多