疑惑 提出問題python
前天同事問我一個問題,爲何這個腳本中的沒有調用A 的__init__。腳本以下:學習
1 class A(object): 2 def __init__(self, *args, **kwargs): 3 print "Call init from %s" %self.__class__ 4 5 def __new__(cls, *args, **kwargs): 6 obj = object.__new__(cls, *args, **kwargs) 7 print "Call new from %s" %obj.__class__ 8 return obj 9 10 11 class B(object): 12 def __init__(self, *args, **kwargs): 13 print "Call init from %s" %self.__class__ 14 15 def __new__(cls, *args, **kwargs): 16 obj = object.__new__(A, *args, **kwargs) 17 print "Call new from %s" %obj.__class__ 18 return obj 19 20 b = B()
其實我也比較奇怪,這個腳本寫的比較奇怪,class B的的__new__返回了A的實例。也只是只執行了B的__new__方法,並無執行A的__init__方法。spa
深刻 迷失debug
遇到這個問題:調試
要深刻首先查看了一下代碼的編譯後的python指令,查看B,是B的__init__方法的指令,code
如上圖,爲了具體查看B()方法是如何調用,就添加了一個方法test_B。B()顯示僅僅是兩條指令blog
LOAD_GLOBALit
CALL_FUNCTIONio
查看Python源代碼,到編譯
PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
ternaryfunc call;
if ((call = func->ob_type->tp_call) != NULL) {
PyObject *result;
if (Py_EnterRecursiveCall(" while calling a Python object"))
return NULL;
result = (*call)(func, arg, kw);
**************看到這裏的時候有點迷失了,不知道tp_call是個什麼東西了,不肯定由typeobject來操做
(這個必須進行反省由於tp_call已已經明確了他來自哪裏)***************
調試 問題解決
最後使出了,大招對Python源代碼進行調試,在Linux上編譯python源代碼加上參數--with-debug, 而後執行gdb -ex r --args python test.py
,
在call_function,do_call,PyObject_Call 執行到以後,打上斷點。看到他運行到了
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
obj = type->tp_new(type, args, kwds);
if (obj != NULL) {
if (!PyType_IsSubtype(obj->ob_type, type))
return obj;
,這個時候我再去看代碼。發現哪裏已經寫好註釋了:
/* If the returned object is not an instance of type,
it won't be initialized. */
好吧,很明確了了。沒有產生和class類型一致的instance,就不會進行初始化。即調用__init__。
問題解決了。。也學習了
要問我怎麼知道在那個地方打斷點,由於我已經看過了代碼,只是理解沒有那麼深。