• Python没有执行__init__


    疑惑 提出问题

    前天同事问我一个问题,为什么这个脚本中的没有调用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__方法。

    深入 迷失

    遇到这个问题:

    要深入首先查看了一下代码的编译后的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__。

    问题解决了。。也学习了

    要问我怎么知道在那个地方打断点,因为我已经看过了代码,只是理解没有那么深。

  • 相关阅读:
    CCS
    CCS
    CCS
    CCS
    CCS
    CCS
    CCS
    CCS
    Java之内部类
    Java之回调模式和ThreadLocal
  • 原文地址:https://www.cnblogs.com/tom-zhao/p/6116853.html
Copyright © 2020-2023  润新知