IPython autoreload 重复调用 Python2 super() 时出错
IPython autoreload gives error for repeated calls to Python2 super()
我正在 IPython 笔记本中制作原型,它正在从我计算机上的模块加载 Python2 代码。我激活了重新加载魔法命令,以便在我更改代码并重新 运行 一个单元格以查看其影响时更容易地在我的文本编辑器和笔记本之间来回切换:
%reload_ext autoreload
%autoreload 2
我在 Python 2.7.10 中工作,因为我使用了一些不能为 3 编译的遗留代码。我的部分工作是扩展此遗留代码中的一些 类 并重载他们的一些方法。但是,我还需要调用一些原始的基本方法来完成重要的工作。例如:
class LegacyBase:
def important_method(self):
#old stuff i'll need
class NewClass(LegacyBase):
#overload base method
def important_method(self):
#do some new stuff
while 1:
#call old method to do stuff
super(NewClass, self).important_method() #use old Python2 super calls :(
#some break conditions
当我第一次在我的笔记本中用一些 NewClass
实例调用 important_method()
时(意思是,在内核重置之后)它 运行 没问题。循环使得 super
调用不止一次发生!没有错误
但是,如果我在我的文本编辑器中为我的新方法修改一些代码并返回到 IPython 单元格并再次调用它,我会在重载 [=] 的行中收到以下错误15=] 调用 super
的地方。
TypeError: super(type, obj): obj must be an instance or subtype of type
注意: 我尝试将我的新方法命名为不同的名称,因为我认为这与重载方法调用有关本身再次,但没有帮助。此外,我希望它们具有相同的名称,因为这是一个 API 方法,我希望遗留代码的用户能够调用他们以前知道的相同方法。
知道如何通过这些 Python2 super
调用在 IPython 笔记本中使用重新加载吗?
谢谢!
您的现有实例仍指向重新加载前的旧 class。
您需要重新创建实例,或更新它们的 __class__
属性:
instance_of_newclass.__class__ = NewClass
重现问题
我使用一个模块 reload_test.py
模仿你的例子:
class LegacyBase:
def important_method(self):
print 'doing'
class NewClass(LegacyBase):
def important_method(self):
for x in range(3):
super(NewClass, self).important_method()
在我的 IPython 笔记本中:
In [1]: %reload_ext autoreload
%autoreload 2
In [2]: import reload_test
In [3]: nc = reload_test.NewClass()
调用方法抛出此异常:
In [4]: nc.important_method()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-09eb0eac244b> in <module>()
----> 1 nc.important_method()
/Users/mike/tmp/reload_test.py in important_method(self)
9
10 for x in range(3):
---> 11 super(NewClass, self).important_method()
TypeError: must be type, not classobj
classLegacyBase
需要继承自object
:
class LegacyBase(object):
def important_method(self):
print 'doing'
class NewClass(LegacyBase):
def important_method(self):
for x in range(3):
super(NewClass, self).important_method()
现在,我可以重现您的问题。第一次工作:
In [5]: nc = reload_test.NewClass()
In [6]: nc.important_method()
doing
doing
doing
在编辑器中修改文件后:
class LegacyBase(object):
def important_method(self):
print 'doing'
class NewClass(LegacyBase):
def important_method(self):
for x in range(3):
super(NewClass, self).important_method()
调用方法抛出异常:
In [7]: nc.important_method()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-09eb0eac244b> in <module>()
----> 1 nc.important_method()
/Users/mike/tmp/reload_test.py in important_method(self)
9
10 for x in range(3):
---> 11 super(NewClass, self).important_method()
TypeError: super(type, obj): obj must be an instance or subtype of type
解决方案
创建一个新实例:
In [8]: nc = reload_test.NewClass()
In [9]: nc.important_method()
doing 2
doing 2
doing 2
实际上这意味着 re-executing 包含 nc = reload_test.NewClass()
的单元格。
可能有点老套,但我发现在构造函数中将父方法设置为新属性会启用 auto-reloading。
class LegacyBase:
def important_method(self):
#old stuff i'll need
class NewClass(LegacyBase):
def __init__(self, *args, **kwargs):
self.__parent_important_method = super(NewClass, self).important_method
super(NewClass, self).__init__(*args, **kwargs)
#overload base method
def important_method(self):
#do some new stuff
while 1:
#call old method to do stuff
self.__parent_important_method()
#some break conditions
我正在 IPython 笔记本中制作原型,它正在从我计算机上的模块加载 Python2 代码。我激活了重新加载魔法命令,以便在我更改代码并重新 运行 一个单元格以查看其影响时更容易地在我的文本编辑器和笔记本之间来回切换:
%reload_ext autoreload
%autoreload 2
我在 Python 2.7.10 中工作,因为我使用了一些不能为 3 编译的遗留代码。我的部分工作是扩展此遗留代码中的一些 类 并重载他们的一些方法。但是,我还需要调用一些原始的基本方法来完成重要的工作。例如:
class LegacyBase:
def important_method(self):
#old stuff i'll need
class NewClass(LegacyBase):
#overload base method
def important_method(self):
#do some new stuff
while 1:
#call old method to do stuff
super(NewClass, self).important_method() #use old Python2 super calls :(
#some break conditions
当我第一次在我的笔记本中用一些 NewClass
实例调用 important_method()
时(意思是,在内核重置之后)它 运行 没问题。循环使得 super
调用不止一次发生!没有错误
但是,如果我在我的文本编辑器中为我的新方法修改一些代码并返回到 IPython 单元格并再次调用它,我会在重载 [=] 的行中收到以下错误15=] 调用 super
的地方。
TypeError: super(type, obj): obj must be an instance or subtype of type
注意: 我尝试将我的新方法命名为不同的名称,因为我认为这与重载方法调用有关本身再次,但没有帮助。此外,我希望它们具有相同的名称,因为这是一个 API 方法,我希望遗留代码的用户能够调用他们以前知道的相同方法。
知道如何通过这些 Python2 super
调用在 IPython 笔记本中使用重新加载吗?
谢谢!
您的现有实例仍指向重新加载前的旧 class。
您需要重新创建实例,或更新它们的 __class__
属性:
instance_of_newclass.__class__ = NewClass
重现问题
我使用一个模块 reload_test.py
模仿你的例子:
class LegacyBase:
def important_method(self):
print 'doing'
class NewClass(LegacyBase):
def important_method(self):
for x in range(3):
super(NewClass, self).important_method()
在我的 IPython 笔记本中:
In [1]: %reload_ext autoreload
%autoreload 2
In [2]: import reload_test
In [3]: nc = reload_test.NewClass()
调用方法抛出此异常:
In [4]: nc.important_method()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-5-09eb0eac244b> in <module>()
----> 1 nc.important_method()
/Users/mike/tmp/reload_test.py in important_method(self)
9
10 for x in range(3):
---> 11 super(NewClass, self).important_method()
TypeError: must be type, not classobj
classLegacyBase
需要继承自object
:
class LegacyBase(object):
def important_method(self):
print 'doing'
class NewClass(LegacyBase):
def important_method(self):
for x in range(3):
super(NewClass, self).important_method()
现在,我可以重现您的问题。第一次工作:
In [5]: nc = reload_test.NewClass()
In [6]: nc.important_method()
doing
doing
doing
在编辑器中修改文件后:
class LegacyBase(object):
def important_method(self):
print 'doing'
class NewClass(LegacyBase):
def important_method(self):
for x in range(3):
super(NewClass, self).important_method()
调用方法抛出异常:
In [7]: nc.important_method()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-09eb0eac244b> in <module>()
----> 1 nc.important_method()
/Users/mike/tmp/reload_test.py in important_method(self)
9
10 for x in range(3):
---> 11 super(NewClass, self).important_method()
TypeError: super(type, obj): obj must be an instance or subtype of type
解决方案
创建一个新实例:
In [8]: nc = reload_test.NewClass()
In [9]: nc.important_method()
doing 2
doing 2
doing 2
实际上这意味着 re-executing 包含 nc = reload_test.NewClass()
的单元格。
可能有点老套,但我发现在构造函数中将父方法设置为新属性会启用 auto-reloading。
class LegacyBase:
def important_method(self):
#old stuff i'll need
class NewClass(LegacyBase):
def __init__(self, *args, **kwargs):
self.__parent_important_method = super(NewClass, self).important_method
super(NewClass, self).__init__(*args, **kwargs)
#overload base method
def important_method(self):
#do some new stuff
while 1:
#call old method to do stuff
self.__parent_important_method()
#some break conditions