Поведение Python super() не является надежным
По какой-то причине метод super()
не всегда ведет себя так, как ожидалось, предпочитая возвращать:
TypeError('super(type, obj): obj must be an instance or subtype of type)'
Я понимаю, что означает ошибка. Я не понимаю, почему это происходит как ошибка. Вот фрагмент кода, который ломается. Все объекты в системе - это новые объекты стиля.
Что действительно интересно, так это то, что эта ошибка не всегда появляется. Я не знаю, что вызывает это. Метод super()
в Retrieval
передает класс 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)
может стать ложным после перезагрузки модулей из-за изменений в ссылках на память, по-видимому.
Изменить: если вы используете приложение web.py в mod_wsgi, убедитесь, что вы отключили автозагрузку:
app = web.application(urls, globals(), autoreload=False)
Ответ 2
Если вы используете reload() как часть вашего рабочего процесса, вам, вероятно, также нужно использовать super(self.__class__, self).__init__
для инициализации наследования.
Я подозреваю, что эта ошибка совпадает с ошибкой id(self.__class__) ==id(Retrieval)
.
Ответ 3
Я не уверен, почему происходит ошибка, но в качестве помощи для отладки вы можете связать вызов 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
Ответ 4
У меня была одна и та же проблема, запустив мой код в ноутбуке jupyter. Я использовал reload, поэтому я перезапустил свое ядро, чтобы следить за ответом Эдуардо Ивенека, чтобы попытаться посмотреть, не возникла ли эта проблема. Тогда мой код сломался. Я обнаружил, что моя проблема связана с несколькими уровнями наследования, где нижний слой был определен над вторым нижним уровнем в модуле.
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
У меня была такая же ошибка, и я заметил, что у меня был дублирующий класс (моя ошибка) в том же файле. Ошибка исчезла, когда я переименовал второй класс 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):