標籤:
通過代碼驗證是最靠譜的:
class Foo(object): def __init__(self): print 'foo init' def __new__(cls,*args,**kwargs): print 'foo new' return object.__new__(cls,*args,**kwargs) foo = Foo()print type(foo)
結果:
>>> foo newfoo init<class '__main__.Foo'>>>>
可以看出來__new__()執行順序比較早,實際上,新式類的__new__()才是真正的初始化函數。
Ps:cls表示一個類,一個當前要被執行個體化的類,參數由py解譯器自動提供。
上述代碼只能論證__new__比__init__更早被調用。但是why?
查了下官方文檔:https://docs.python.org/2.7/reference/datamodel.html#object.__new__
object.__new__(cls[, ...]):
建立一個執行個體:Called to create a new instance of class cls.
靜態方法:__new__() is a static method that takes the class of which an instance was requested as its first argument.
通過調用父輩的__new__:super(currentclass, cls).__new__(cls[, ...])
建立好執行個體才__init__:If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...])
object.__init__(cls[,...]):
有一句話:__new__() to create it, and __init__() to customise it
通過官方文檔就能瞭解__new__()和__init__()的先後順序了。但是why?
有的時候真討厭自己喜歡尋根問底,好吧,直接上源碼:C:\Python-2.7.9rc1\Objects\typeobject.c:
__init__()對應的實現代碼:
static intobject_init(PyObject *self, PyObject *args, PyObject *kwds){ int err = 0; if (excess_args(args, kwds)) { PyTypeObject *type = Py_TYPE(self); if (type->tp_init != object_init && type->tp_new != object_new) { err = PyErr_WarnEx(PyExc_DeprecationWarning, "object.__init__() takes no parameters", 1); } else if (type->tp_init != object_init || type->tp_new == object_new) { PyErr_SetString(PyExc_TypeError, "object.__init__() takes no parameters"); err = -1; } } return err;}
__new__()對應的實現代碼:
static PyObject *object_new(PyTypeObject *type, PyObject *args, PyObject *kwds){ int err = 0; if (excess_args(args, kwds)) { if (type->tp_new != object_new && type->tp_init != object_init) { err = PyErr_WarnEx(PyExc_DeprecationWarning, "object() takes no parameters", 1); } else if (type->tp_new != object_new || type->tp_init == object_init) { PyErr_SetString(PyExc_TypeError, "object() takes no parameters"); err = -1; } } if (err < 0) return NULL; if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) { static PyObject *comma = NULL; PyObject *abstract_methods = NULL; PyObject *builtins; PyObject *sorted; PyObject *sorted_methods = NULL; PyObject *joined = NULL; const char *joined_str; /* Compute ", ".join(sorted(type.__abstractmethods__)) into joined. */ abstract_methods = type_abstractmethods(type, NULL); if (abstract_methods == NULL) goto error; builtins = PyEval_GetBuiltins(); if (builtins == NULL) goto error; sorted = PyDict_GetItemString(builtins, "sorted"); if (sorted == NULL) goto error; sorted_methods = PyObject_CallFunctionObjArgs(sorted, abstract_methods, NULL); if (sorted_methods == NULL) goto error; if (comma == NULL) { comma = PyString_InternFromString(", "); if (comma == NULL) goto error; } joined = PyObject_CallMethod(comma, "join", "O", sorted_methods); if (joined == NULL) goto error; joined_str = PyString_AsString(joined); if (joined_str == NULL) goto error; PyErr_Format(PyExc_TypeError, "Can't instantiate abstract class %s " "with abstract methods %s", type->tp_name, joined_str); error: Py_XDECREF(joined); Py_XDECREF(sorted_methods); Py_XDECREF(abstract_methods); return NULL; } return type->tp_alloc(type, 0);}
我們就關注問題本身,why __new__比__init__更早,看到python原始碼(C語言實現):
可以看到object_init()實際上並沒有什麼代碼,只是兩個if判斷,而object_new()才是各種屬性搞起:
static PyObject *comma = NULL;
PyObject *abstract_methods = NULL;
PyObject *builtins;
PyObject *sorted;
PyObject *sorted_methods = NULL;
PyObject *joined = NULL;
所以問題得到解決:__new__()的確是建立一個新的執行個體,__init__()在執行個體上面進行customize(定製)。
貌似__new__()是新式類(繼承自object)內建有的。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
python __new__()和__init__()哪個更早?