Constructors in Python: overwriting __new__ and the singleton pattern

About all object-oriented languages allow you to overwrite the constructor of a particular self-defined type. In Java (and C#) this looks somewhat like that:

public class A(object) {
  constructor A() {
    // Do Something
  }
}

If you think the parameters somehow merit the abortion of the object creation, you can only throw an exception. You only can do that. An object of (in this case) type A is always returned. You can’t even return a different object or an object of a subclass of A. This convention led to the factory pattern in which a static method is called to decide which specific constructor of which specific class to run. Since the method is declared as returning the supertype, it can return any subptype as well. But the factory-pattern can sometimes get out of hand.

If you get started with python you commonly see __init__(self [, args]) as the method you need to overwrite in order to get a constructor.

class A(object):
  def __init__(self):
    pass

And it is true that this is exactly what is written above.
Note: in python, methods are objects (and could be swapped any time). Therefore the own instance cannot be bound outside the method scope and it is always passed by the calling instance as the first parameter. Therefore any non-static method of a class starts with „self“ (or „s“ or whatever you want to call it) as its first parameter.

So __init__ is, as is the constructor in C# or Java, only called when the instance has already been created. So why is it called a constructor then? Historical reasons, for one. But with statically typed languages you can overload the constructor and build your instance from different parameters. A dynamically typed language like python has no method overloading. It is still good for initializing properties of the particular instance.

But there is another cool method in python which you can overwrite: __new__(C [,args]) in which the class to create an instance of is passed in C and the rest of the arguments in args. And now you can build something like this:

class A(object):
  pass

class B(object):
  def __new__(C):
    return A()

In statically typed languages it is almost always true that A() returns an object of type A. But in python, this does not need to be true. You can put your factory right there as the constructor of the superclass and it looks really neat.

And we can now imagine even cooler stuff like returning a singleton that might look something like this:

class Singletonclass(object):
  pass

class A(object):
  s = None
  def __new__(C):
    if A.s is None:
      A.s = Singletonclass()
    return A.s

So if we invoke the constructor for A(), we will always get the same instance of Singletonclass. But we could even put it in one singular class:

class Singleton(object):
  def __new__(C):
    if not '_singleton_instance' in C.__dict__:
      C._singleton_instance = object.__new__(C)
    return C._singleton_instance

  def __init__(self):
    if not '_ready' in dir(self):
      # init code here
      self._ready = True

Since __init__ is still called every time an instance is requested (with two seperate classes only one actual instance of the singleton has been requested), you have to work around that by only executing initialization code once.

I am sure you can think of many creative ways to overwrite and use __new__ now that you know how it works. Please make your factories look neat 🙂

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.