Python super() 行为不可靠

Posted

技术标签:

【中文标题】Python super() 行为不可靠【英文标题】:Python super() behavior not dependable 【发布时间】:2012-04-01 02:45:57 【问题描述】:

由于某种原因,super() 方法并不总是按预期运行,选择返回:

TypeError('super(type, obj): obj must be an instance or subtype of type)'

我了解错误的含义。我不明白为什么它会出现错误。这是正在破坏的代码的 sn-p。系统中的所有对象都是新样式对象。

真正有趣的是,这个错误并不总是出现。我不知道是什么原因造成的。 Retrieval 中的 super() 方法传递 Retrieval 类,然后将其本身作为一个对象,据我所知,super() 究竟是如何应该被调用。

有什么想法吗?

在文件DBConnection.py中:

class DBAdminConnection(object):
    def __init__(self):
        self.user = DBUserConnection().user 
        self.submissions = DBSubmissionConnection()

在文件 Retrieval.py

class Retrieval(DBConnection.DBAdminConnection): 
    def __init__(self, username=None, password=None, unique_key=None):
        super(Retrieval,self).__init__()
        if username and password:
            self.username = username
            self.user.login(username,password, config.DATABASE)
            if self.user.error:
                raise UserLoginError(username)
        self.unique_key = unique_key

【问题讨论】:

【参考方案1】:

您是否正在以某种方式重新加载模块?如果是这样,这可以解释这个错误。

isinstance(self,DBAdminConnection) 在重新加载模块后可能会因为内存引用的更改而变为 false。

编辑:如果您在 mod_wsgi 下运行 web.py 应用程序,请确保禁用自动重载:

app = web.application(urls, globals(), autoreload=False)

【讨论】:

这是通过 webpy 运行的。所以这是一个确定的可能性。特别是因为如果我杀死应用程序实例并重新生成它,问题就会消失。哇。现在问题变成了如何解决它。 @TomThorogood:你是如何运行你的应用程序的?你在使用 mod_wsgi 吗? 我不认为我正在这样做。我现在补充一下!我没有使用 mod_wsgi。我正在使用带有 spawn-fcgi 的 nginx。我会尝试禁用自动重载。非常感谢! 我将把它标记为已解决;你所建议的一切都很有意义,我相信解决方案是唯一的(除非 webpy 中存在错误)。 正如你所说的那样发生在我身上,因为我在 IPython 中使用了 %load_ext autoreload %autoreload 2 中的类【参考方案2】:

我不确定为什么会发生错误,但作为调试的帮助,您可以将对super 的调用包装在try/except 块中,并在引发异常时进行数据转储。像这样的:

class Retrieval(DBConnection.DBAdminConnection): 
    def __init__(self, username=None, password=None, unique_key=None):
        try:
            super(Retrieval,self).__init__()
        except TypeError, e:
            print "Failure initialising Retrieval --> self: %r"
            raise
        if username and password:
            self.username = username
            self.user.login(username,password, config.DATABASE)
            if self.user.error:
                raise UserLoginError(username)
        self.unique_key = unique_key

【讨论】:

您的意思是您不确定吗?因为你让我一时抱了希望。 /咧嘴 哈哈。不用担心!谢谢你的东西。我进行了一些调试;我只是在清理 SO 的代码。【参考方案3】:

如果您在工作流程中使用 reload(),显然您还需要使用 super(self.__class__, self).__init__ 进行继承初始化。

我怀疑你会发现这个错误与id(self.__class__) ==id(Retrieval) 失败相吻合。

【讨论】:

super(self.__class__, self) 总是错误的。如果您进一步子类化,它将成为一个无限循环。 如果不进一步子类化怎么办,有时可以吗?【参考方案4】:

我刚刚遇到了同样的问题,在 jupyter notebook 中运行我的代码。我正在使用重新加载,所以我重新启动了我的内核以跟进 Eduardo Ivanec 的响应,尝试看看这是否是问题所在。然后我的代码坏了。我发现我的问题与多个继承层有关,其中底层定义在模块中的第二个底层之上

class MyClass1(object):
'''example class 1'''

class MyClass2(MyClass1):
'''example class 2'''
    def __init__(self):
    super(MyClass2, self).__init__()

class MyClass4(MyClass3):
'''example class 4 - no __init__ definition'''

class MyClass3(MyClass2):
'''example class 3 - no __init__ definition'''

当我将 MyClass4 移到 MyClass3 下时,它解决了问题。

这可能是一个菜鸟错误,所以它可能无法解决上述原始问题的原因,但我想我会发布,以防有​​其他菜鸟,像我一样,犯同样的错误。

(抱歉,如果我的风格有误,这是我在 Stack Overflow 上的第一篇文章。:))

【讨论】:

【参考方案5】:

我遇到了同样的错误,然后我注意到我在同一个 file.py 中有重复的类(我的错误)。当我将第二个 A 类重命名为 B 类时,错误消失了

#Just some example below, not real code
class A (object):

    def fun(self):
        super(A, self).fun()

class A (object): ##This second class with same name (A) caused the error

   def some_fun(self,x,y):

【讨论】:

以上是关于Python super() 行为不可靠的主要内容,如果未能解决你的问题,请参考以下文章

不可靠信号

为啥 Java Future.get(timeout) 不可靠?

核心数据级联删除不可靠?

使用python的不可靠的硒webdriver单击

避免贫血域模型如何与 ORM、依赖注入和可靠方法一起使用

可靠地检测基于 PhantomJS 的垃圾邮件机器人