I know (?) about theory behind __new__
constructor in Python, but what I ask about is common practice -- for what purpose is this constructor really (!) used?
I've read about initializing immutable objects (the logic is moved from __init__
to __new__
), anything else? Factory pattern?
Once again, please note the difference:
__new__
can be used -- I am not interested__new__
is used -- I am :-)I don't write anything in Python, my knowledge is from reading, not from experience.
Where you can actually answer the question: Common practice of new constructor?
The point of __new__
is to create an empty object instance that __init__
then initializes. Reimplementing __new__
you have full control of the instance you create, but you stop short of actually using the __init__
method to do any further processing. I can give you two cases where this is useful: automatic creation of methods and deserialization from disk of a class with a smart constructor. These are not the only ways you can solve these two problems. Metaclasses are another, more flexible way, but as any tool, you have different degrees of complexity you may want to get.
Automatic creation of methods
suppose you want to have a class that has a given set of properties. You can take control how these properties are initialized with code like this
class Foo(object):
properties = []
def __new__(cls, *args):
instance = object.__new__(cls, *args)
for p in cls.properties:
setattr(instance, p, 0)
return instance
class MyFoo(Foo):
properties = ['bar', 'baz']
def __init__(self):
pass
f=MyFoo()
print dir(f)
the properties you want are directly initialized to zero. You can do a lot of smart tricks, like doing the properties list dynamically. All objects instantiated will have those methods. A more complex case of this pattern is present in Django Models, where you declare the fields and get a lot of automatic stuff for free, thanks to __new__
big brother, metaclasses.
Deserialization from disk
Suppose you have a class with a given constructor that fills the fields of the class from an object, such as a process:
class ProcessWrapper(object):
def __init__(self, process):
self._process_pid = process.pid()
def processPid(self):
return self._process_pid
If you now serialize this information to disk and want to recover it, you can't initialize via the constructor. So you write a deserialization function like this, effectively bypassing the __init__
method you can't run.
def deserializeProcessWrapperFromFile(filename):
# Get process pid from file
process = ProcessWrapper.__new__()
process._process_pid = process_pid
return process
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