Where is the constructor of the class in Python?

Asked

Viewed 8,390 times

7

Definition of Wikipedia.

The builder is a method which is generally responsible for allocating the necessary resources to the operation of the object beyond the initial definition of the variables of status (attributes).

In Python the method is usually used __init__ to define the values of attributes, this is what I understand about this method, i.e., in my view it is a constructor. See example for illustration:

class Carro(object):
    def __init__(self, modelo, ano): #Construtor da classe.
        self.modelo = modelo
        self.ano = ano

meuCarro = Carro("Jeep 4x4", 2015)

print("Modelo: %s" % meuCarro.modelo)
print("Ano: %d" % meuCarro.ano)

However, in the research which I did, I discovered that the method __init__ is not the builder class, rather the method called when an object is required. I have now become confused as to where is the location of a builder of a Python class. Where builder?

2 answers

4

the Method __init__ is the initializer of the class, so much so that the moment it is executed you already have the instance created (self), in python the class constructor method is __new__:

class Foo:
    def __new__(cls):
        return cls()

Notice how different from __init__ the method __new__ need to return a value, in case the instance of the class being created. See official documentation for more details.

An example of using the method __new__ is in the creation of objects singletons:

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

However, in 99% of cases, you don’t need (and maybe shouldn’t) to change your class constructor method.

  • 2

    Do not forget that classes that do not inherit from "Object" should only be used in Python3. Doing this in Python2 creates "old-style" classes that are incompatible with many of the things that have been added to Python in the last 15 years (yes, old-style is OLD) - and worse, it’s hard to find the error.

  • I haven’t forgotten, but it is clear to me that whoever asked the question is using python3 by print as a function (and I want to believe that he has not omitted any import, as for example from __future__ import print_function)

  • But you have to make it clear to other people who arrive here. The question is not tagged as Python3. (Well, that we can correct)

4


What is a builder

This is a technicality and we can consider him as the constructor. In fact he is an initiator, as he had already written in previous question, but the initializer will be called every time a new object is created, just after calling the __new__ which will be the object’s memory allocator. This allocator is provided by the language if you do not define one, which is rarely necessary, usually in immutable objects can be interesting.

And that’s it, if you do a little deeper research you’ll see that everyone, day by day, will call __init__ builder. If you don’t call it a constructor then every language I know is using the wrong name, because what they call a constructor is also an initializer. They also often call the allocator implicitly and it is usually not necessary to define it in all classes. Of course, if you’re going to be thorough, the terminology isn’t quite the same.

__del__ is the destructor, right? Or is it just a "de-initiator", or just a de-locator? For all intents and purposes, it destroys the object. It is the opposite of the __new__ or the opposite of __init__? The documentation says he is a destructor. So one of the two is the constructor :).

The construction of the object in Python takes place in two steps, which is also true in several languages. It is not always apparent because the allocation is often little explored. In C++, for example, it is possible to override the operator new to create a custom allocation. In C# or Java it is not possible. But note that in these languages the constructor is only an initializer, and by chance it will always be called the allocator, which is fixed, before initializing the members, but the construction is initialization. So we can say that the initializer is the constructor. And of course it can never be called before calling the allocator.

Constructor Expression

What you can do is create a constructor expression, which is a way to give the consumer of that class a way to explicitly do all the object construction and, obviously, you should do the allocation and initialization in some way, even calling the methods that already know how to do this, which would not make sense if it was to do exactly the same thing. And of course you need to know what you’re doing so you don’t make mistakes. It’s a way to give more flexibility to building.

To create a way for the class to do activities other than allocation and startup, you need to give it the ability to be called as a function. This is done by creating a method __call__. So:

class A(object):
    def __init__(self):
        print("init")
    def __call__(self):
        print("call ")

a = A() #imprime init
a() #imprime call

I put in the Github for future reference.

If both have the same signature, __init__ will be called, unless you call __call explicitly, simply: A()(). The __init__ will always be called before.

Examples of use of __call__.

I wouldn’t call it a builder.

Factory method

It is still possible to create a static method (without the self) that can be called to invoke the construction of the object, but I do not see this with good eyes. It does not seem to me idiomatic.

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

Additional reading

To documentation about Python objects is a good read to understand all this. A article that talks a lot about these magical methods.

  • I have now noticed that in the last line of the example it should be a() #imprime call, for __call__ is called when invoking the instance, not the class. Probably a typo, but may confuse the reader.

  • @fernandosavio yes, thank you.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.