Python:总是使用__new__而不是__init__?
我明白__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这方面适合我的头好。
从guido's post(感谢@ fraca7)一个可能的答案:
例如,泡菜模块中,
__new__
使用反序列化对象时创建实例。在这种情况下,会创建实例,但不会调用__init__
方法。
还有其他相似的答案?
我接受这个答案为“是”我自己的问题:
我想知道是否有任何
__init__
能做到这一点__new__
不能?
是的,与__new__
不同,您在取出过程中不会执行在__init__
方法中执行的操作。 __new__
无法作出此区分。
好吧,在谷歌上找__new__ vs __init__
告诉我this。
长话短说,__new__
返回一个新的对象实例,而__init__
什么也没有返回,只是初始化类成员。
编辑:要真正回答你的问题,你应该永远不需要重写__new__
,除非你是不可变类型的子类。
Guido最近谈到: http://python-history.blogspot.com/2010/06/inside-story- on-new-style-classes.html – fraca7 2010-06-28 10:38:15
还有其他一些使用'__new__'的原因,例如flyweight模式。 – 2010-06-28 11:29:39
因此,一个班级的班级通常是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__()
。
对我而言,这并没有真正回答OP的问题。你说过“__init __()'可以做的事情是'__new __()'可以做的事情的一个子集”,但这正是OP的观点,不是吗?如果这句话是真的,那么'__init __()'可以被安全弃用,因为它可以做的任何事情'__new __()'都可以做到。 – Ray 2017-08-17 10:22:37
@Ray **你的结论没有遵循你的前提。**虽然这句话*表面上是真的,但是'__init __()'不能由于所有显而易见的原因被安全弃用 - 特别是**(A)**需要保持与现有Python生态系统的向后兼容性*和* **(B)** __new __()'API(其设计要求明确返回一个实例)与'__init __()'的合约脆弱性API(其设计没有这样的限制)。 '__new __()'会导致API违规,这是不好的; '__init __()'不*,这很好。 – 2018-02-08 04:55:51
[为什么在一个类中定义了'\ _ \ _ new__'和'\ _ \ _ init__'](http:// stackoverflow。在这个主题上的老问题:[Python的使用\ _ \ _ new__和\ _ \ _ init__?](http:/ /问题/ 2017876/Why-defined-new-and-init-all-in-a-class) – 2012-08-03 05:51:18
/stackoverflow.com/questions/674304/pythons-use-of-new-and-init) – 2010-06-28 10:15:01