Питання, яке я збираюся задати, здається, є дублікатом використання 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__
, не є котлован, оскільки котлован ніколи не змінюється. Іноді вам потрібно замінити саме цей код чимось іншим.