Câu hỏi tôi sắp hỏi dường như là một bản sao của việc sử dụng __new__ và __init__ của Python? , nhưng bất kể, nó vẫn chưa rõ ràng với tôi chính xác sự khác biệt thực tế giữa __new__
và __init__
là gì.
Trước khi bạn vội vàng nói với tôi rằng đó __new__
là để tạo ra các đối tượng và __init__
là để khởi tạo các đối tượng, hãy để tôi nói rõ: tôi hiểu điều đó. Trên thực tế, sự khác biệt đó là khá tự nhiên đối với tôi, vì tôi có kinh nghiệm về C ++ nơi chúng tôi có vị trí mới , điều này tương tự tách biệt việc phân bổ đối tượng khỏi khởi tạo.
Các Python C API hướng dẫn giải thích nó như thế này:
Thành viên mới chịu trách nhiệm tạo các đối tượng (trái ngược với khởi tạo) của loại. Nó được hiển thị trong Python như là
__new__()
phương thức. ... Một lý do để thực hiện một phương thức mới là để đảm bảo các giá trị ban đầu của các biến thể hiện .
Vì vậy, yeah - tôi hiểu những gì __new__
nó làm, nhưng mặc dù vậy, tôi vẫn không hiểu tại sao nó hữu ích trong Python. Ví dụ đưa ra nói rằng __new__
có thể hữu ích nếu bạn muốn "đảm bảo các giá trị ban đầu của các biến thể hiện". Chà, chính xác thì __init__
nó sẽ làm gì?
Trong hướng dẫn API C, một ví dụ được hiển thị trong đó Loại mới (được gọi là "Noddy") được tạo và __new__
chức năng của Loại được xác định. Kiểu Noddy chứa một thành viên chuỗi được gọi first
và thành viên chuỗi này được khởi tạo thành một chuỗi trống như vậy:
static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
.....
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
.....
}
Lưu ý rằng không có __new__
phương thức được xác định ở đây, chúng ta sẽ phải sử dụng PyType_GenericNew
, đơn giản là khởi tạo tất cả các thành viên biến đối tượng thành NULL. Vì vậy, lợi ích duy nhất của __new__
phương thức là biến thể hiện sẽ bắt đầu dưới dạng một chuỗi rỗng, trái ngược với NULL. Nhưng tại sao điều này lại hữu ích, vì nếu chúng ta quan tâm đến việc đảm bảo các biến đối tượng của chúng ta được khởi tạo thành một giá trị mặc định, chúng ta có thể thực hiện điều đó trong __init__
phương thức không?
__new__
không phải là bản mẫu, vì bản mẫu không bao giờ thay đổi. Đôi khi bạn cần thay thế mã cụ thể đó bằng một cái gì đó khác nhau.