Pertanyaan yang akan saya tanyakan tampaknya merupakan duplikat dari penggunaan Python untuk __new__ dan __init__? , tetapi terlepas dari itu, masih belum jelas bagi saya apa perbedaan praktis antara __new__
dan __init__
.
Sebelum Anda buru-buru memberi tahu saya bahwa __new__
ini untuk membuat objek dan __init__
untuk menginisialisasi objek, izinkan saya menjelaskan: Saya mengerti. Pada kenyataannya, perbedaan itu cukup alami bagi saya, karena saya memiliki pengalaman dalam C ++ di mana kami memiliki penempatan baru , yang juga memisahkan alokasi objek dari inisialisasi.
The Python C API tutorial menjelaskan seperti ini:
Anggota baru bertanggung jawab untuk membuat (bukan menginisialisasi) objek jenis. Itu diekspos dalam Python sebagai
__new__()
metode. ... Salah satu alasan untuk menerapkan metode baru adalah untuk memastikan nilai awal variabel instan .
Jadi, ya - saya mendapatkan apa yang __new__
dilakukan, tetapi meskipun demikian, saya masih tidak mengerti mengapa ini berguna dalam Python. Contoh yang diberikan mengatakan bahwa __new__
mungkin berguna jika Anda ingin "memastikan nilai awal variabel instan". Nah, bukankah itu tepatnya yang __init__
akan dilakukan?
Dalam tutorial C API, contoh ditampilkan di mana Tipe baru (disebut "Noddy") dibuat, dan fungsi Type __new__
didefinisikan. Tipe Noddy berisi anggota string yang disebut first
, dan anggota string ini diinisialisasi ke string kosong seperti:
static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
.....
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
.....
}
Perhatikan bahwa tanpa __new__
metode yang didefinisikan di sini, kita harus menggunakan PyType_GenericNew
, yang hanya menginisialisasi semua anggota variabel instan ke NULL. Jadi satu-satunya manfaat dari __new__
metode ini adalah bahwa variabel instance akan mulai sebagai string kosong, sebagai lawan dari NULL. Tetapi mengapa ini pernah berguna, karena jika kita peduli untuk memastikan variabel instan kita diinisialisasi ke beberapa nilai default, kita bisa saja melakukannya dalam __init__
metode ini?
__new__
bukan boilerplate, karena boilerplate tidak pernah berubah. Terkadang Anda perlu mengganti kode tertentu dengan sesuatu yang berbeda.