2010-06-28 55 views
26

我明白__init____new__是如何工作的。 我想知道是否有什么__init__可以做到__new__不可以?Python:总是使用__new__而不是__init__?

即可以使用__init__通过以下方式代替:

class MySubclass(object): 
    def __new__(cls, *args, **kwargs): 
     self = super(MySubclass, cls).__new__(cls, *args, **kwargs) 
     // Do __init__ stuff here 
     return self 

我问,因为我想使Python OO这方面适合我的头好。

+0

[为什么在一个类中定义了'\ _ \ _ new__'和'\ _ \ _ init__'](http:// stackoverflow。在这个主题上的老问题:[Python的使用\ _ \ _ new__和\ _ \ _ init__?](http:/ /问题/ 2017876/Why-defined-new-and-init-all-in-a-class) – 2012-08-03 05:51:18

+0

/stackoverflow.com/questions/674304/pythons-use-of-new-and-init) – 2010-06-28 10:15:01

回答

4

guido's post(感谢@ fraca7)一个可能的答案:

例如,泡菜模块中,__new__使用反序列化对象时创建实例。在这种情况下,会创建实例,但不会调用__init__方法。

还有其他相似的答案?


我接受这个答案为“是”我自己的问题:

我想知道是否有任何__init__能做到这一点__new__不能?

是的,与__new__不同,您在取出过程中不会执行在__init__方法中执行的操作。 __new__无法作出此区分。

2

好吧,在谷歌上找__new__ vs __init__告诉我this

长话短说,__new__返回一个新的对象实例,而__init__什么也没有返回,只是初始化类成员。

编辑:要真正回答你的问题,你应该永远不需要重写__new__,除非你是不可变类型的子类。

+1

Guido最近谈到: http://python-history.blogspot.com/2010/06/inside-story- on-new-style-classes.html – fraca7 2010-06-28 10:38:15

+2

还有其他一些使用'__new__'的原因,例如flyweight模式。 – 2010-06-28 11:29:39

21

因此,一个班级的班级通常是type,当您拨打Class()时,的Class的班级处理该班级。我相信type.__call__()实现或多或少是这样的:

def __call__(cls, *args, **kwargs): 
    # should do the same thing as type.__call__ 
    obj = cls.__new__(cls, *args, **kwargs) 
    if isinstance(obj, cls): 
     obj.__init__(*args, **kwargs) 
    return obj 

直接回答你的问题是否定的,事情__init__()可以做的(变化/“初始化”指定实例)是的东西一个子集, __new__()可以做(创建或以其他方式选择它想要的任何对象,在对象返回之前对该对象执行任何操作)。

但是,使用这两种方法都很方便。使用__init__()更简单(它不需要创建任何东西,它不需要返回任何东西),我相信最好的做法是始终使用__init__(),除非您有特定的理由使用__new__()

+0

对我而言,这并没有真正回答OP的问题。你说过“__init __()'可以做的事情是'__new __()'可以做的事情的一个子集”,但这正是OP的观点,不是吗?如果这句话是真的,那么'__init __()'可以被安全弃用,因为它可以做的任何事情'__new __()'都可以做到。 – Ray 2017-08-17 10:22:37

+0

@Ray **你的结论没有遵循你的前提。**虽然这句话*表面上是真的,但是'__init __()'不能由于所有显而易见的原因被安全弃用 - 特别是**(A)**需要保持与现有Python生态系统的向后兼容性*和* **(B)** __new __()'API(其设计要求明确返回一个实例)与'__init __()'的合约脆弱性API(其设计没有这样的限制)。 '__new __()'会导致API违规,这是不好的; '__init __()'不*,这很好。 – 2018-02-08 04:55:51

相关问题