Python: always use __new__ instead of __init__?
我知道__init__和__new__是如何工作的。我想知道有没有什么东西能让__init__做不到?
也就是说,可以用以下模式替换__init__:
1 2 3 4 5
| class MySubclass(object):
def __new__(cls, *args, **kwargs):
self = super(MySubclass, cls).__new__(cls, *args, **kwargs)
// Do __init__ stuff here
return self |
我在问,因为我想让PythonOO的这个方面更好地适合我的头脑。
- 关于这个主题的老问题:python使用了uuu new_uuuu和uuu init_uuuuuu?
- 在一个类中,可能重复了为什么定义了"uu new_uuuu"和"uu init_uuu"
所以,一个类的类通常是type,当您调用Class()时,Class类上的__call__()方法处理这个问题。我相信type.__call__()的实施或多或少是这样的:
1 2 3 4 5 6
| 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__()。
- 对我来说,这并不能真正回答手术的问题。你说"__init__()能做的事情是__new__()能做的事情的一个子集",但这正是操作的重点,不是吗?如果这句话是真的,那么__init__()就可以被安全地否决,因为它所能做的一切,__new__()也可以做到。
- @雷,你的结论跟不上你的前提。虽然这句话表面上是正确的,但由于所有明显的原因(特别是,(a)需要保持与现有的python生态系统的向后兼容性,以及(b)__new__()API的合同脆弱性(其设计要求实例显式返回)与__init__()API(其设计不施加此类约束)的比较。__new__()邀请违反API,这是坏的;__init__()不邀请违反API,这是好的。
一个可能的答案来自Guido的帖子(谢谢@fraca7):
For example, in the pickle module, __new__ is used to create instances when unserializing objects. In this case, instances are created, but the __init__ method is not invoked.
号
还有其他类似的答案吗?
我接受这个答案作为我自己的问题的"是"。
I'm wondering if there is anything __init__ can do that __new__ cannot?
号
是的,与__new__不同,您在__init__方法中执行的操作不会在解压过程中执行。__new__不能作出这种区分。
好吧,在谷歌上找__new__ vs __init__就说明了这一点。
长话短说,__new__返回一个新的对象实例,而__init__不返回任何内容,只初始化类成员。
编辑:要实际回答您的问题,除非您要对不可变类型进行子类化,否则不需要重写__new__。
- 吉多最近谈到过:python history.blogspot.com/2010/06/…
- 使用__new__还有其他原因,例如flyweight模式。