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.
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.
– jsbueno
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
)– drgarcia1986
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)
– jsbueno