Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有办法在IPython重新加载后手动修复“super()”的操作(避免TypeError)?_Python_Python 2.7_Ipython_Typeerror_Ipython Magic - Fatal编程技术网

有没有办法在IPython重新加载后手动修复“super()”的操作(避免TypeError)?

有没有办法在IPython重新加载后手动修复“super()”的操作(避免TypeError)?,python,python-2.7,ipython,typeerror,ipython-magic,Python,Python 2.7,Ipython,Typeerror,Ipython Magic,下面是一个人为制造的玩具示例,用于触发我遇到的问题: 我有几个类,假设它们在本地文件'issue.py'中: class A(object): def save(self): # fancy stuff pass class B(A):

下面是一个人为制造的玩具示例,用于触发我遇到的问题:

我有几个类,假设它们在本地文件'issue.py'中:

class A(object):
    def save(self):
        # fancy stuff                                                                                                          
        pass

class B(A):
    def save(self):
        # misc stuff                                                                                                           
        super(B, self).save()

class C(B):
    pass
我在IPython会话中使用它们,可能是这样的:

In [1]: %load_ext autoreload

In [2]: %autoreload 2

In [3]: from issue import A, B, C

In [4]: c = C()

In [5]: c.foo = 'whatever'

In [6]: c.save()
到目前为止,一切顺利。但后来我意识到a类“奇特的东西”中有一个bug,并在那里做了一个小的编辑——甚至可能只是添加了一点日志记录。然后我想重复
save()

[7]中的
:c.save()
---------------------------------------------------------------------------
TypeError回溯(最近一次调用上次)
在()
---->1 c.保存()
/用户/scratch/Documents/dev2015/gensim\u venv/src/gensim develop/docs/notebooks/scratch~/issue.py保存(self)
7 def保存(自):
8#杂项材料
---->9 super(B,self).save()
10
11 C(B)类:
TypeError:super(type,obj):obj必须是类型的实例或子类型
哦,不!。重新加载类后会出现可怕的
TypeError
,而较旧的实例会保留一些较旧的超类!SO和其他地方都在讨论这个问题,但没有明确的复苏方案

但是,碰巧的是,我非常非常希望能够在我的旧
c
实例上运行稍微更新的
A.save()
。(我的内存中有20GB以上的数据,大约需要一天半的时间来生成这些数据,这些数据将通过超类方法以首选方式保存。我已经通过其他手动方法保存了足够多的数据,我认为我能够在重新启动的IPython内核中重建
c
。但是,尽管我仍然拥有真实的对象,但我还是要做很多准备。)请尝试对修补后的
a.save()
进行实际测试,甚至可能在完全重启内核之前对其进行更多修复/测试。)

因此,我对任何策略或技巧感兴趣,不管它们在其他情况下有多不明智,都可以将
c
强制到当前的类定义中,直到
c.save()
起作用

有什么想法吗


我希望任何适用于这个玩具示例的东西都能在我的真实设置中工作,这是一个基于CPython 2.7.10的IPython)。(但是,在实际情况中,这三个类位于不同的文件中。)

您可以将更新的类重新分配给实例:

from issue import A, B, C
c.__class__ = C
此时,
self
将再次成为重新加载的类层次结构的适当实例。注意,您也需要在这里重新绑定globals;模块重新加载,而不是类的全局引用

如果有多个模块的更复杂的设置,则需要替换对旧类的所有引用。如果您在表单的任何模块中有导入:

from some_module import Bar

class Foo(Bar):
    # ...
然后,当重新加载某个模块时,
Bar
不会被重新绑定。通过避免绑定到全局变量,可以避免强制重新加载和绑定依赖项;改为仅绑定模块:

import some_module

class Foo(some_module.Bar):
    # ...
之后,只需重新绑定模块对象。或者只是手动重新加载所有涉及的模块,毕竟您的数据存在于实例中

演示:

>>A类(对象):
...     def保存(自我):
...         # 花哨的东西
...         通过
... 
>>>B(A)类:
...     def保存(自我):
...         # 杂项材料
...         super(B,self).save()
... 
>>>丙(乙)类:
...     通过
... 
>>>c=c()
>>>c.foo=‘随便什么’
>>>c.保存()
>>> 
>>>#重新定义类会破坏实例
... 
>>>A类(对象):
...     def保存(自我):
...         # 花哨的东西
...         通过
... 
>>>B(A)类:
...     def保存(自我):
...         # 杂项材料
...         super(B,self).save()
... 
>>>丙(乙)类:
...     通过
... 
>>>isinstance(c,c)
假的
>>>c.保存()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第4行,保存
TypeError:super(type,obj):obj必须是类型的实例或子类型
>>> 
>>>#通过重新绑定类来解决问题
... 
>>>c.。\uuuu类\uuuuu=c
>>>isinstance(c,c)
真的
>>>c.保存()

在Python3中,使用新的
super()。\uuuu init\uuuu()
语法而不是
super(B,self)。\uuuu init\uuuuu()
为我解决了一个类似的问题。

您是否尝试过创建新的
C
的新实例,然后用旧的
C
中的数据手动覆盖其数据?这将如何或是否起作用取决于
c
存储什么样的数据,以及如何存储,但这是我想到的第一种方法。这也是我想到的。但是,即使在玩具示例中,如果尝试创建
c2
,它在
c2.save()上也会出现相同的错误,因此它的超类层次结构不是固定的。(在我的实际设置中,也有一个类似的类型错误影响C的
\uuuuu init\uuuu
方法,它对B的
\uuuuu init\uuuuu
执行super()操作。我尝试了
C.\uuu class\uuuuu=C
,但随后
C.save()
触发了完全相同的错误。@gojomo:那么会话中的
C
是否仍然绑定到旧类?然后从问题导入A、B、C中发出另一个
。宾果,看起来是这样做的!现在在启发示例的真实会话中尝试……唉,“真实”设置中仍然存在问题。在那里,B和C是独立的文件一个模块;A来自另一个模块。要尝试编辑每个文件(由IPython的更改检测拾取),然后显式导入…@gojomo:您正在使用全局导入;
来自mod import classname
;如果您导入模块,则不必重新加载
import some_module

class Foo(some_module.Bar):
    # ...
>>> class A(object):
...     def save(self):
...         # fancy stuff                                                                                                          
...         pass
... 
>>> class B(A):
...     def save(self):
...         # misc stuff                                                                                                           
...         super(B, self).save()
... 
>>> class C(B):
...     pass
... 
>>> c = C()
>>> c.foo = 'whatever'
>>> c.save()
>>> 
>>> # Re-defining the classes breaks the instance
... 
>>> class A(object):
...     def save(self):
...         # fancy stuff                                                                                                          
...         pass
... 
>>> class B(A):
...     def save(self):
...         # misc stuff                                                                                                           
...         super(B, self).save()
... 
>>> class C(B):
...     pass
... 
>>> isinstance(c, C)
False
>>> c.save()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in save
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> 
>>> # Fixing the issue by rebinding the class
... 
>>> c.__class__ = C
>>> isinstance(c, C)
True
>>> c.save()