super () завершается с ошибкой: аргумент TypeError 1 должен быть типом, а не classobj, если родительский элемент не наследуется от объекта

Я получаю ошибку, которую не могу понять. Любая подсказка, что не так с моим образцом кода?

class B:
    def meth(self, arg):
        print arg

class C(B):
    def meth(self, arg):
        super(C, self).meth(arg)

print C().meth(1)

Я получил образец кода теста с помощью встроенного метода «super».

Вот ошибка:

Traceback (most recent call last):
  File "./test.py", line 10, in ?
    print C().meth(1)
  File "./test.py", line 8, in meth
    super(C, self).meth(arg)
TypeError: super() argument 1 must be type, not classobj

К вашему сведению, вот помощь (супер) от самого python:

Help on class super in module __builtin__:

class super(object)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super(C, self).meth(arg)
 |

person Ehsan Foroughi    schedule 11.11.2009    source источник
comment
возможный дубликат python super () вызывает TypeError! Почему?   -  person user    schedule 06.09.2013
comment
Мет ?? Это термин программирования, или ... понимаете? Просьба уточнить.   -  person Cplusplusplus    schedule 08.10.2015
comment
@Cplusplusplus: вероятно, это означает метод ;-)   -  person ShadowFlame    schedule 25.10.2015


Ответы (4)


Ваша проблема в том, что класс B не объявлен как класс «нового стиля». Измените это так:

class B(object):

и это будет работать.

super() и все подклассы / суперклассы работают только с классами нового стиля. Я рекомендую вам выработать привычку всегда вводить это (object) в любом определении класса, чтобы убедиться, что это класс нового стиля.

Классы старого стиля (также известные как «классические» классы) всегда имеют тип classobj; классы нового стиля относятся к типу type. Вот почему вы получили сообщение об ошибке:

TypeError: super() argument 1 must be type, not classobj

Попробуйте сами убедиться в этом:

class OldStyle:
    pass

class NewStyle(object):
    pass

print type(OldStyle)  # prints: <type 'classobj'>

print type(NewStyle) # prints <type 'type'>

Обратите внимание, что в Python 3.x все классы выполнены в новом стиле. Вы по-прежнему можете использовать синтаксис из классов старого стиля, но вы получите класс нового стиля. Итак, в Python 3.x у вас не будет этой проблемы.

person steveha    schedule 11.11.2009
comment
интересно, я обнаружил эту точную проблему при запуске bottle.py (bottlepy.org), который выдает аналогичную ошибку (TypeError: должно быть type, а не classobj) работает на Py27, но не на Py33. - person bootload; 03.09.2013
comment
В Python 3.x больше нет классов старого стиля. Код, использующий объявление старого стиля, по-прежнему объявляет класс нового стиля, поэтому эта ошибка не может возникнуть в Python 3.x. - person steveha; 30.11.2014
comment
Если класс B недоступен для редактирования, вы должны отредактировать класс A, чтобы не пытаться использовать super(); класс A должен работать с классом старого стиля, и, возможно, лучший способ сделать это - сделать класс A классом старого стиля. Конечно, я рекомендую просто обновить всю вашу программу для работы на Python 3.x, чтобы все классы были в новом стиле, независимо от того, что вы делаете; если такой вариант доступен, это лучший вариант. - person steveha; 09.07.2018
comment
У меня такая же проблема, но мой базовый класс объявлен как class B(object):. Я получаю эту ошибку из-за использования @mock.patch('module.B', autospec=B) непосредственно перед тестовым примером. Есть мысли, как это исправить? - person MikeyE; 05.08.2018

Кроме того, если вы не можете изменить класс B, вы можете исправить ошибку, используя множественное наследование.

class B:
    def meth(self, arg):
        print arg

class C(B, object):
    def meth(self, arg):
        super(C, self).meth(arg)

print C().meth(1)
person frmdstryr    schedule 23.08.2013
comment
Я не мог не оставить комментарий, его следует принять как «стандартный» ответ. - person http8086; 09.12.2014
comment
Для будущих гуглеров, застрявших на Python 2.6: это ответ, который вы, вероятно, захотите! Когда вы не можете изменить базовый класс (например, вы подклассифицируете класс стандартной библиотеки), это изменение вашего собственного класса исправляет super (). - person coredumperror; 11.12.2015
comment
У меня это сработало, вы можете объяснить, как это работает? - person subro; 16.05.2017
comment
@subro, это делает ваш класс классом нового стиля (где объект класса имеет тип type), в то же время создавая подкласс класса старого стиля (чей объект класса имеет тип classobj). super() работает с классами нового стиля, но не с классами старого стиля. - person MarSoft; 15.03.2018

Если версия python 3.X, ничего страшного.

Я думаю, что ваша версия python - 2.X, супер будет работать при добавлении этого кода

__metaclass__ = type

так что код

__metaclass__ = type
class B:
    def meth(self, arg):
        print arg
class C(B):
    def meth(self, arg):
        super(C, self).meth(arg)
print C().meth(1)
person yanghaogn    schedule 05.08.2015

Я также столкнулся с опубликованной проблемой, когда использовал python 2.7. Он отлично работает с python 3.4

Чтобы заставить его работать в python 2.7, я добавил атрибут __metaclass__ = type вверху моей программы, и это сработало.

__metaclass__: упрощает переход от классов старого стиля к классам нового стиля.

person JON    schedule 28.02.2017