疑惑 提出问题
前天同事问我一个问题,为什么这个脚本中的没有调用A 的__init__。脚本如下:
1
class
A(object):
2
def
__init__(self, *args, **kwargs):
3print"Call init from %s" %self.__class__ 4 5def__new__(cls, *args, **kwargs):
6 obj = object.__new__(cls, *args, **kwargs)
7print"Call new from %s" %obj.__class__ 8return obj
91011class B(object):
12def__init__(self, *args, **kwargs):
13print"Call init from %s" %self.__class__1415def__new__(cls, *args, **kwargs):
16 obj = object.__new__(A, *args, **kwargs)
17print"Call new from %s" %obj.__class__18return obj
1920 b = B()
其实我也比较奇怪,这个脚本写的比较奇怪,class B的的__new__返回了A的实例。也只是只执行了B的__new__方法,并没有执行A的__init__方法。
深入 迷失
遇到这个问题:
要深入首先查看了一下代码的编译后的python指令,查看B,是B的__init__方法的指令,
如上图,为了具体查看B()方法是如何调用,就添加了一个方法test_B。B()显示仅仅是两条指令
LOAD_GLOBAL
CALL_FUNCTION
查看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__。
问题解决了。。也学习了
要问我怎么知道在那个地方打断点,因为我已经看过了代码,只是理解没有那么深。
原文:http://www.cnblogs.com/tom-zhao/p/6116853.html
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!