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
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 to type.__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 a foo
slot -- and you want it to be instantiated with an initializer for the int
and one for the .foo
. As int
is immutable, that part has to happen in __new__
, so pedantically one could code:
>>> class x(int):
... def __new__(cls, i, foo):
... self = int.__new__(cls, i)
... return self
... def __init__(self, i, foo):
... self.foo = foo
... __slots__ = 'foo',
...
>>> a = x(23, 'bah')
>>> print a
23
>>> print a.foo
bah
>>>
In practice, for a case this simple, nobody would mind if you lost the __init__
and just moved the self.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.
__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:
class Meters(object):
def __new__(cls, value):
return int(value / 3.28083)
If you call Meters(6)
you will not actually create an instance of Meters
, but an instance of int
. 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 on SortedDict
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With