A pergunta que estou prestes a fazer parece ser uma duplicata do uso de __new__ e __init__ pelo Python? , mas, independentemente disso, ainda não está claro para mim exatamente qual é a diferença prática entre __new__e __init__é.
Antes de você se apressar para me dizer que __new__é para criar objetos e __init__para inicializar objetos, deixe-me esclarecer: entendi. De fato, essa distinção é bastante natural para mim, já que tenho experiência em C ++, onde temos um novo posicionamento , que também separa a alocação de objetos da inicialização.
O tutorial da API do Python C explica assim:
O novo membro é responsável por criar (em vez de inicializar) objetos do tipo. É exposto no Python como o
__new__()método. ... Um motivo para implementar um novo método é garantir os valores iniciais das variáveis da instância .
Então, sim - eu entendo o que __new__faz, mas, apesar disso, ainda não entendo por que é útil no Python. O exemplo dado diz que __new__pode ser útil se você deseja "garantir os valores iniciais das variáveis da instância". Bem, não é exatamente isso que __init__fará?
No tutorial da API C, é mostrado um exemplo em que um novo Type (chamado "Noddy") é criado e a __new__função do Type é definida. O tipo Noddy contém um membro da cadeia de caracteres chamado firste esse membro da cadeia é inicializado em uma cadeia vazia da seguinte forma:
static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
.....
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
.....
}
Observe que, sem o __new__método definido aqui, teríamos que usar PyType_GenericNew, que simplesmente inicializa todos os membros da variável de instância para NULL. Portanto, o único benefício do __new__método é que a variável de instância começará como uma sequência vazia, em oposição a NULL. Mas por que isso é útil, pois se nos importamos em garantir que nossas variáveis de instância sejam inicializadas com algum valor padrão, poderíamos ter feito isso no __init__método?
__new__não é clichê, porque o clichê nunca muda. Às vezes, você precisa substituir esse código específico por algo diferente.