Питання, яке я збираюся задати, здається, є дублікатом використання Python __new__ та __init__? , Але незалежно від того , що до цих пір незрозуміло мені саме те , що практична різниця між __new__і __init__є.
Перш ніж ви поспішите сказати мені, що __new__для створення об'єктів і __init__для ініціалізації об'єктів, дозвольте мені зрозуміти: я це розумію. Насправді, ця відмінність для мене цілком природна, оскільки я маю досвід роботи в C ++, де у нас є нове розміщення , яке аналогічно відокремлює розподіл об'єктів від ініціалізації.
Підручник API Python C пояснює це так:
Новий член відповідає за створення (на відміну від ініціалізації) об'єктів типу. Він розкривається в Python як
__new__()метод. ... Однією з причин реалізації нового методу є забезпечення початкових значень змінних екземплярів .
Так, так - я розумію, що __new__робить, але, незважаючи на це, я все ще не розумію, чому це корисно в Python. Наведений приклад говорить, що __new__може бути корисним, якщо ви хочете "запевнити початкові значення змінних екземплярів". Ну, чи не саме це __init__буде робити?
У підручнику з API API показаний приклад, коли створюється новий Тип (називається "Noddy") і визначається __new__функція Type . Тип Noddy містить член-рядок, який називається first, і цей рядовий член ініціалізується до порожнього рядка таким чином:
static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
.....
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
.....
}
Зауважте, що без __new__методу, визначеного тут, нам доведеться використовувати PyType_GenericNew, який просто ініціалізує всі члени змінної екземпляра до NULL. Тому єдиною перевагою __new__методу є те, що змінна інстанція починається як порожня рядок, на відміну від NULL. Але чому це завжди корисно, оскільки якби ми піклувались про те, щоб наші змінні екземпляри були ініціалізовані до якогось значення за замовчуванням, ми могли би це зробити в __init__методі?
__new__, не є котлован, оскільки котлован ніколи не змінюється. Іноді вам потрібно замінити саме цей код чимось іншим.