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() 行为不可靠的主要内容,如果未能解决你的问题,请参考以下文章