Вопрос, который я собираюсь задать, кажется дубликат использования 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__
?