问题描述
我只是想简化我的一个类,并引入了一些与 风格相同的功能享元设计模式.
但是,我有点困惑为什么 __init__ 总是在 __new__ 之后调用.我没想到会这样.谁能告诉我为什么会发生这种情况以及我如何实现此功能?(除了将实现放入感觉很hacky的 __new__ 之外).
这是一个例子:
class A(object): _dict = dict() def __new__(cls): if 'key' in A._dict: print "EXISTS" return A._dict['key'] else: print "NEW" return super(A, cls).__new__(cls) def __init__(self): print "INIT" A._dict['key'] = self print "" a1 = A() a2 = A() a3 = A()
输出:
NEW INIT EXISTS INIT EXISTS INIT
为什么?
推荐答案
当你需要控制时使用 __new__创建一个新实例.利用__init__ 当您需要控制新实例的初始化时.
__new__ 是创建实例的第一步.它首先被调用,并且是负责退回新的你的类的实例.相比之下,__init__ 不返回任何内容;它只负责初始化创建后的实例.
一般来说,您不需要覆盖 __new__ 除非你是子类化不可变类型,例如str、int、unicode 或元组.
来自:http://mail.python.org/pipermail/导师/2008-4月/061426.html
您应该考虑到您尝试做的事情通常是通过 Factory 完成的,这就是最好的方法.使用 __new__ 不是一个好的清洁解决方案,因此请考虑使用工厂.这里有一个很好的工厂示例.
问题描述
I'm just trying to streamline one of my classes and have introduced some functionality in the same style as the flyweight design pattern.
However, I'm a bit confused as to why __init__ is always called after __new__. I wasn't expecting this. Can anyone tell me why this is happening and how I implement this functionality otherwise? (apart from putting the implementation into the __new__ which feels quite hacky).
Here's an example:
class A(object): _dict = dict() def __new__(cls): if 'key' in A._dict: print "EXISTS" return A._dict['key'] else: print "NEW" return super(A, cls).__new__(cls) def __init__(self): print "INIT" A._dict['key'] = self print "" a1 = A() a2 = A() a3 = A()
Outputs:
NEW INIT EXISTS INIT EXISTS INIT
Why?
推荐答案
Use __new__ when you need to control the creation of a new instance. Use __init__ when you need to control initialization of a new instance.
__new__ is the first step of instance creation. It's called first, and is responsible for returning a new instance of your class. In contrast, __init__ doesn't return anything; it's only responsible for initializing the instance after it's been created.
In general, you shouldn't need to override __new__ unless you're subclassing an immutable type like str, int, unicode or tuple.
From: http://mail.python.org/pipermail/tutor/2008-April/061426.html
You should consider that what you are trying to do is usually done with a Factory and that's the best way to do it. Using __new__ is not a good clean solution so please consider the usage of a factory. Here you have a good factory example.