Python:总是使用 __new__ 而不是 __init__?
Posted
技术标签:
【中文标题】Python:总是使用 __new__ 而不是 __init__?【英文标题】:Python: always use __new__ instead of __init__? 【发布时间】:2011-03-09 01:43:17 【问题描述】:我了解__init__
和__new__
的工作原理。
我想知道有什么__init__
可以做到__new__
不能做到吗?
即可以使用__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 的这一方面更适合我。
【问题讨论】:
关于该主题的旧问题:Python’s use of __new__ and __init__ ? why defined '__new__' and '__init__' all in a class的可能重复 【参考方案1】:因此,类的类通常是type
,当您调用Class()
时,Class
的类上的__call__()
方法会处理它。我相信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__()
,除非你有特定的理由使用@ 987654331@.
【讨论】:
对我来说,这并不能真正回答 OP 的问题。您说“__init__()
可以做的事情是__new__()
可以做的事情的一个子集”,但这正是 OP 的重点,不是吗?如果这句话是真的,那么__init__()
可以安全地被弃用,因为它可以做的任何事情,__new__()
也可以做。
@Ray 你的结论不符合你的前提。虽然这句话是表面上是正确的,__init__()
不能安全地弃用所有显而易见的原因 - 值得注意的是,(A) 需要保持与现有 Python 生态系统的向后兼容性和 (B) __new__()
API(其设计要求显式返回实例)与__init__()
API(其设计没有施加此类约束)。 __new__()
会引发 API 违规,这很糟糕; __init__()
没有,这很好。【参考方案2】:
guido's post 的一个可能答案(感谢@fraca7):
例如,在 pickle 模块中,
__new__
用于在反序列化对象时创建实例。在这种情况下,会创建实例,但不会调用__init__
方法。
还有其他类似的答案吗?
我接受这个答案作为我自己的问题的“是”:
我想知道是否有什么
__init__
可以做到__new__
不能做到?
是的,与__new__
不同,您在__init__
方法中放置的操作不会在解酸过程中执行。 __new__
无法区分。
【讨论】:
【参考方案3】:嗯,在谷歌上寻找__new__ vs __init__
显示this。
长话短说,__new__
返回一个新的对象实例,而__init__
什么也不返回,只是初始化类成员。
编辑:要真正回答您的问题,您永远不需要覆盖 __new__
,除非您是不可变类型的子类。
【讨论】:
Guido 最近谈到了这个:python-history.blogspot.com/2010/06/… 还有其他原因使用__new__
,例如享元模式。以上是关于Python:总是使用 __new__ 而不是 __init__?的主要内容,如果未能解决你的问题,请参考以下文章
详解Python中的__new__、__init__、__call__三个特殊方法