i think you can defined either '__init__
' or '__new__
' in a class,but why all defined in django.utils.datastructures.py.
my code:
class a(object):
def __init__(self):
print 'aaa'
def __new__(self):
print 'sss'
a()#print 'sss'
class b:
def __init__(self):
print 'aaa'
def __new__(self):
print 'sss'
b()#print 'aaa'
datastructures.py:
class SortedDict(dict):
"""
A dictionary that keeps its keys in the order in which they're inserted.
"""
def __new__(cls, *args, **kwargs):
instance = super(SortedDict, cls).__new__(cls, *args, **kwargs)
instance.keyOrder = []
return instance
def __init__(self, data=None):
if data is None:
data = {}
super(SortedDict, self).__init__(data)
if isinstance(data, dict):
self.keyOrder = data.keys()
else:
self.keyOrder = []
for key, value in data:
if key not in self.keyOrder:
self.keyOrder.append(key)
and what circumstances the SortedDict.__init__
will be call.
thanks
My only guess is that in this case, they (author of this class) want the keyOrder list to exist on the class even before
SortedDict.__init__
is called.Note that SortedDict calls
super()
in its__init__
, this would ordinarily go todict.__init__
, which would probably call__setitem__
and the like to start adding items.SortedDict.__setitem__
expects the.keyOrder
property to exist, and therein lies the problem (since.keyOrder
isn't normally created until after the call tosuper()
.) It's possible this is just an issue with subclassingdict
because my normal gut instinct would be to just initialize.keyOrder
before the call tosuper()
.The code in
__new__
might also be used to allow SortedDict to be subclassed in a diamond inheritance structure where it is possibleSortedDict.__init__
is not called before the first__setitem__
and the like are called. Django has to contend with various issues in supporting a wide range of python versions from 2.3 up; it's possible this code is completely un-neccesary in some versions and needed in others.There is a common use for defining both
__new__
and__init__
: accessing class properties which may be eclipsed by their instance versions without having to dotype(self)
orself.__class__
(which, in the existence of metaclasses, may not even be the right thing).For example:
Finally,
__new__
can actually return an instance of a wrapper or a completely different class from what you thought you were instantiating. This is used to provide metaclass-like features without actually needing a metaclass.In my opinion, there was no need of overriding
__new__
in the example you described. Creation of an instance and actual memory allocation happens in__new__
,__init__
is called after__new__
and is meant for initialization of instance serving the job of constructor in classical OOP terms. So, if all you want to do is initialize variables, then you should go for overriding__init__
. The real role of__new__
comes into place when you are using Metaclasses. There if you want to do something like changing attributes or adding attributes, that must happen before the creation of class, you should go for overriding__new__
.Consider, a completely hypothetical case where you want to make some attributes of class private, even though they are not defined so (I'm not saying one should ever do that).
Again, It's just for instructional purposes I'm not suggesting one should do anything like this.
__new__
and__init__
do completely different things. The method__init__
initiates a new instance of a class --- it is a constructor.__new__
is a far more subtle thing --- it can change arguments and, in fact, the class of the initiated object. For example, the following code:If you call
Meters(6)
you will not actually create an instance ofMeters
, but an instance ofint
. You might wonder why this is useful; it is actually crucial to metaclasses, an admittedly obscure (but powerful) feature.You'll note that in Python 2.x, only classes inheriting from
object
can take advantage of__new__
, as you code above shows.The use of
__new__
you showed in django seems to be an attempt to keep a sane method resolution order onSortedDict
objects. I will admit, though, that it is often hard to tell why__new__
is necessary. Standard Python style suggests that it not be used unless necessary (as always, better class design is the tool you turn to first).You can define either or both of
__new__
and__init__
.__new__
must return an object -- which can be a new one (typically that task is delegated totype.__new__
), an existing one (to implement singletons, "recycle" instances from a pool, and so on), or even one that's not an instance of the class. If__new__
returns an instance of the class (new or existing),__init__
then gets called on it; if__new__
returns an object that's not an instance of the class, then__init__
is not called.__init__
is passed a class instance as its first item (in the same state__new__
returned it, i.e., typically "empty") and must alter it as needed to make it ready for use (most often by adding attributes).In general it's best to use
__init__
for all it can do -- and__new__
, if something is left that__init__
can't do, for that "extra something".So you'll typically define both if there's something useful you can do in
__init__
, but not everything you want to happen when the class gets instantiated.For example, consider a class that subclasses
int
but also has afoo
slot -- and you want it to be instantiated with an initializer for theint
and one for the.foo
. Asint
is immutable, that part has to happen in__new__
, so pedantically one could code:In practice, for a case this simple, nobody would mind if you lost the
__init__
and just moved theself.foo = foo
to__new__
. But if initialization is rich and complex enough to be best placed in__init__
, this idea is worth keeping in mind.