Вопрос, который я собираюсь задать, кажется дубликат использования Python __new__ и __init__?, но, несмотря на это, мне все еще неясно, что именно практическая разница между __new__ и __init__ равна.
Прежде чем спешить, чтобы сказать мне, что __new__ предназначен для создания объектов, а __init__ - для инициализации объектов, позвольте мне быть ясным: Я получаю это. На самом деле это различие вполне естественно для меня, поскольку у меня есть опыт работы на С++, где у нас размещение нового, что аналогично отделяет выделение объектов от инициализации.
Учебник Python C API объясняет это следующим образом:
Новый член отвечает за создание (в отличие от инициализации) объектов типа. Он подвергается воздействию Python как метод
__new__().... Одной из причин внедрения нового метода является обеспечение начальных значений переменные экземпляра.
Итак, да, я понимаю, что делает __new__, но, несмотря на это, я до сих пор не понимаю, почему он полезен в Python. В приведенном примере говорится, что __new__ может оказаться полезным, если вы хотите "заверить начальные значения переменных экземпляра". Ну, разве это не то, что сделает __init__?
В учебнике API C показан пример, где создается новый тип (называемый "Noddy" ), и определена функция Type __new__. Тип 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__?