对于重复调用Python2 super()

时间:2015-09-27 00:42:39

标签: python python-2.7 ipython-notebook super

我在IPython笔记本中对原型进行原型设计,该笔记本从我的计算机上的模块加载Python2代码。我激活重新加载魔术命令,以便在我更改代码并重新运行单元格以查看其影响时,更容易在文本编辑器和笔记本之间来回切换:

%reload_ext autoreload
%autoreload 2

我在Python 2.7.10中工作,因为我使用了一些不能编译的遗留代码。我的部分工作是扩展这些遗留代码中的一些类并重载其中的一些方法。但是,我还需要调用一些原始的基本方法来完成重要的工作。例如:

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

当我第一次在我的笔记本中调用important_method() NewClass实例时(意味着,在内核重置后),它运行正常。循环使得super调用不止一次发生!没有错误

但是,如果我在我的文本编辑器中将一些代码修改为我的新方法并返回到IPython单元并再次调用它,那么我在重载important_method()的行中会出现以下错误{ {1}}打电话。

super

注意: 我尝试将新方法命名为另一个名称,因为我认为这与重载方法再次调用自身有关但是没有帮助。此外,我希望它们是相同的名称,因为这是一种API方法,我希望遗留代码的用户能够调用他们之前知道的相同方法。

知道如何使用这些Python2 TypeError: super(type, obj): obj must be an instance or subtype of type 调用在IPython笔记本中重新加载吗?

谢谢!

3 个答案:

答案 0 :(得分:2)

您的现有实例仍然指向重新加载之前的旧类。

您需要重新创建实例,或更新其__class__属性:

instance_of_newclass.__class__ = NewClass

答案 1 :(得分:1)

重现问题

我使用模型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

班级LegacyBase需要继承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

实际上,这意味着只需重新执行包含nc = reload_test.NewClass()的单元格。

答案 2 :(得分:0)

可能有点hacky,但我发现在构造函数中将父方法设置为新属性会启用自动重新加载。

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