autoreload和package导致TypeError:super(type,obj):obj必须是类型为

时间:2015-09-09 13:55:35

标签: python ipython

我有几个文件的python代码,为方便起见,我打包了这些文件,最后是my_package目录下的以下3个文件:

__init__.py

内容:

from file1 import *
from file2 import *

file1.py内容:

class Base(object):
    pass

file2.py内容:

from file1 import Base 
class Derived(Base):
    def __init__(self):
        return super(Derived, self).__init__()

然后我在IPython中执行:

>>>%autoreload 2
>>>import my_package
>>>t = my_package.Derived()

到目前为止一切顺利。 但后来我对file2.py进行了更改,比如说添加了一个虚拟属性。 现在当我执行:

>>>t = my_package.Derived()
>>>      2 class Derived(Base):
>>>      3     def __init__(self):
>>>----> 4         return super(Derived, self).__init__()
>>>      5 
>>>      6 dumm = 'asdf'
>>>
>>>TypeError: super(type, obj): obj must be an instance or subtype of type

在我重新启动IPython控制台之前,这并没有消失。为什么不进行自动重载正确处理?如果我将Base和Derived放入单个模块文件而不是包中,那么一切都有效。

2 个答案:

答案 0 :(得分:11)

我不是IPython的用户,所以我不能确切地说出发生了什么,但我想这是在from file2 import *文件中使用__init__.py的症状。

当您使用Derived创建package.Derived课程的实例时,您没有获得该课程的最新版本,但是该软件包是第一个时的旧版本加载并运行from file2 import *语句。当您修改模块代码并重新加载IPython时,它改变了package.file2.Derived,但没有改变package.Derived

但是,该类的旧版本仍然具有对其模块命名空间的引用,并且当它试图在super调用中按名称查找自己时,它会找到该类的较新版本。这就是您收到错误的原因,因为两个Derived类不相同。

如果您直接访问package.file2.Derived,则可能会避免此问题。这将始终让您进入该类的当前版本,该版本不应该与super调用有任何问题。请注意,如果在修改模块之前仍然存在该类的实例,则可能仍然存在问题(但这可能不是很令人惊讶)。

答案 1 :(得分:2)

在Python 3中,使用新的super().__init__()代替super(Derived, self).__init__()为我解决了这个问题