Класс Python наследует объект


1246

Есть ли какая-либо причина для объявления класса наследовать object?

Я только что нашел код, который делает это, и я не могу найти вескую причину, почему.

class MyClass(object):
    # class code follows...

2
Это создает новый стиль класса .
Слоты

116
Ответ на этот вопрос (хотя и простой) найти довольно сложно. Поиск в Google, например, «базовый класс объектов Python» или аналогичные, приводит к появлению страниц и страниц учебных пособий по объектно-ориентированному программированию. Апвоттинг, потому что это первая ссылка, которая привела меня к поисковым терминам "старые и новые объекты Python"
суперспирант

Ответы:


765

Есть ли какая-либо причина для объявления класса наследовать object?

В Python 3, кроме совместимости между Python 2 и 3, нет причин . В Python 2 много причин .


История Python 2.x:

В Python 2.x (начиная с 2.2) есть два стиля классов в зависимости от наличия или отсутствия objectв качестве базового класса:

  1. классические классы стиля : они не имеют objectбазового класса:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
  2. «новые» классы стилей : они имеют, прямо или косвенно (например, наследуют от встроенного типа ), objectв качестве базового класса:

    >>> class NewSpam(object):           # directly inherit from object
    ...    pass
    >>> NewSpam.__bases__
    (<type 'object'>,)
    >>> class IntSpam(int):              # indirectly inherit from object...
    ...    pass
    >>> IntSpam.__bases__
    (<type 'int'>,) 
    >>> IntSpam.__bases__[0].__bases__   # ... because int inherits from object  
    (<type 'object'>,)

Без сомнения, при написании класса вы всегда захотите перейти на классы нового стиля. Льготы для этого многочисленны, чтобы перечислить некоторые из них:

  • Поддержка дескрипторов . В частности, следующие дескрипторы стали возможными с помощью дескрипторов:

    1. classmethod: Метод, который получает класс в качестве неявного аргумента вместо экземпляра.
    2. staticmethod: Метод, который не получает неявный аргумент selfв качестве первого аргумента.
    3. Свойства с property: Создание функций для управления получением, установкой и удалением атрибута.
    4. __slots__Сохраняет потребление памяти классом, а также ускоряет доступ к атрибутам. Конечно, это накладывает ограничения .
  • __new__Статический метод: позволяет настроить как новые создаются экземпляры класса.

  • Порядок разрешения методов (MRO) : в каком порядке будут искать базовые классы класса при попытке определить, какой метод вызывать.

  • Связанные с MRO, superзвонки . Также смотрите, super()считается супер.

Если вы не наследуете object, забудьте об этом. Более полное описание предыдущих пунктов маркировки наряду с другими преимуществами «новых» классов стилей можно найти здесь .

Одним из недостатков классов нового стиля является то, что сам класс требует больше памяти. Если, конечно, вы не создаете много объектов класса, я сомневаюсь, что это будет проблемой, и это будет негативное погружение в море позитива.


История Python 3.x:

В Python 3 все упрощено. Существуют только классы нового стиля (именуемые просто классами), поэтому единственное отличие в добавлении objectсостоит в том, что требуется ввести еще 8 символов. Эта:

class ClassicSpam:
    pass

полностью эквивалентно (кроме их имени :-) этому:

class NewSpam(object):
     pass

и к этому:

class Spam():
    pass

Все имеют objectпо своему __bases__.

>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]

Итак, что нужно сделать?

В Python 2: всегда наследовать от objectявно . Получи льготы.

В Python 3: наследовать, objectесли вы пишете код, который пытается быть независимым от Python, то есть он должен работать как в Python 2, так и в Python 3. В противном случае это не имеет никакого значения, поскольку Python вставляет его для вас. за кулисами.


«в зависимости от наличия или отсутствия встроенного типа в качестве базового класса» => на самом деле речь идет не об «отсутствии или наличии встроенного типа в качестве базового класса», а в том, наследует ли класс - прямо или косвенно - от него object. IIRC был момент, когда еще не все встроенные типы были перенесены в классы нового стиля.
Бруно Desthuilliers

@brunodesthuilliers У меня сложилось впечатление, что все встроенные типы наследуются от object. У меня есть Python 2.2.3, и после быстрой проверки я не смог найти нарушителя, но позже я перефразирую ответ, чтобы сделать его более понятным. Было бы интересно, если бы вы могли найти пример, мое любопытство задето.
Димитрис Фасаракис Хиллиард

Честно говоря (см. «IIRC» в моем предыдущем комментарии), я не уверен на 101% в этом вопросе (все ли встроенные типы были уже преобразованы в классы нового стиля, когда были введены классы нового стиля) - я мог бы просто быть простым неправильно, или это могло касаться только некоторых стандартных типов lib (но не встроенных). Но все же я думаю, что было бы лучше уточнить, что в основе лежит класс нового стиля object.
Bruno Desthuilliers

7
слишком плохой стекопоток делает только upvote = upvote + 1 для таких любопытных ответов, хотелось бы, чтобы upvote + = N
PirateApp

1
staticmethodи classmethodотлично работает даже на уроках старого стиля. propertyСорта работает для чтения в классах старого стиля, просто не перехватывает записи (поэтому, если вы присваиваете имя, экземпляр получает атрибут с заданным именем, который скрывает свойство). Также обратите внимание, что __slots__улучшение скорости доступа к атрибутам в основном сводится к устранению потерь, связанных с доступом к атрибутам классов нового стиля, поэтому это не совсем выгодно для классов нового стиля (хотя экономия памяти - это точка продажи).
ShadowRanger

540

Python 3

  • class MyClass(object): = Новый стиль
  • class MyClass:= Новый стиль класса (неявно наследуется от object)

Python 2

  • class MyClass(object): = Новый стиль
  • class MyClass:= СТАРЫЙ СТИЛЬ КЛАСС

Пояснение :

При определении базовых классов в Python 3.x вы можете удалить objectиз определения. Тем не менее, это может открыть дверь для серьезного трудно отслеживаемой проблемы ...

Python представил классы нового стиля еще в Python 2.2, и к настоящему времени классы старого стиля действительно довольно старые. Обсуждение классов в старом стиле скрыто в документах 2.x и отсутствует в документах 3.x.

Проблема заключается в том , что синтаксис для классов старого стиля в Python 2.x является такой же , как альтернативный синтаксис для новых классов в Python 3.x . Python 2.x по-прежнему очень широко используется (например, GAE, Web2Py), и любой код (или кодер), невольно вносящий определения классов в стиле 3.x в код 2.x, в конечном итоге будет иметь некоторые серьезно устаревшие базовые объекты. А поскольку классы старого стиля ни на чём не находятся, они, вероятно, не будут знать, что их поразило.

Так что просто разберитесь в этом долгий путь и сэкономьте разработчику 2.x слезы.


13
«При определении базовых классов в Python 3.x вы можете исключить объект из определения. Однако это может открыть дверь для серьезной проблемы, которую трудно отследить…» К каким проблемам вы относитесь?
Эйдис

6
@Aidis: Я думаю, они имеют в виду, что код, который работает как на Py2, так и на Py3, подойдет для Py3, но будет разбит на Py2, если он опирается на функции класса нового стиля. Лично, если я пишу такой код, я пропускаю явное наследование и просто помещаю его __metaclass__ = typeв верхнюю часть модуля (после from __future__ import absolute_import, division, print_functionстроки :-)); это хак совместимости в Py2, который делает все впоследствии определенные классы в модуле новым стилем по умолчанию, а в Py3 он полностью игнорируется (просто случайная глобальная переменная сидит без дела), поэтому он безвреден.
ShadowRanger

400

Да, это объект «нового стиля». Это была функция, представленная в python2.2.

Новые объекты типа имеют различную объектную модель для классических объектов, и некоторые вещи не будут работать должным образом со старыми объектами типа, например, super(), @propertyи дескрипторы. См. Эту статью для хорошего описания того, что новый класс стиля.

Так что ссылка для описания различий: В чем разница между старым стилем и новым стилем классов в Python?


110
+1 это. Обратите внимание, что классы старого стиля исчезли в Python 3, поэтому вам нужно наследовать только от objectPython 2.

9
Это не настоящий ответ. Я просто даю ссылку на другие статьи. Я думаю, что ответ Ярина должен быть принят как ответ на этот вопрос.
alwbtc

2
@alwbtc: В этом ответе тоже есть что-то новое. Например, упоминание о «super ()» привело меня к другому важному [здесь] ( stackoverflow.com/questions/576169/… ).
ViFI

34

История от изучения Python трудный путь :

Оригинальное представление Python класса было сломано во многих серьезных отношениях. К тому времени, когда эта ошибка была признана, было уже слишком поздно, и они должны были поддержать это. Чтобы решить проблему, им нужен был стиль «новый класс», чтобы «старые классы» продолжали работать, но вы можете использовать новую, более правильную версию.

Они решили, что будут использовать слово «объект» в нижнем регистре как «класс», от которого вы наследуете, чтобы создать класс. Это сбивает с толку, но класс наследует от класса с именем «объект», чтобы создать класс, но на самом деле это не объект, а класс, но не забывайте наследовать от объекта.

Также просто для того, чтобы вы знали, в чем разница между классами нового стиля и классами старого стиля, это то, что классы нового стиля всегда наследуются от objectкласса или от другого класса, унаследованного от object:

class NewStyle(object):
    pass

Другой пример:

class AnotherExampleOfNewStyle(NewStyle):
    pass

В то время как базовый класс старого стиля выглядит так:

class OldStyle():
    pass

И дочерний класс старого стиля выглядит так:

class OldStyleSubclass(OldStyle):
    pass

Вы можете видеть, что базовый класс старого стиля не наследуется ни от какого другого класса, однако классы старого стиля могут, конечно, наследовать друг от друга. Наследование от объекта гарантирует, что определенная функциональность доступна в каждом классе Python. Новые классы стиля были введены в Python 2.2


8
Вызов корневого класса objectне так уж и запутан, и на самом деле он довольно стандартный. Smalltalk имеет корневой класс с именем Objectи корневой метакласс Class. Почему? Потому что, так же как Dogи класс для собак, Objectэто класс для объектов и Classкласс для классов. Java, C #, ObjC, Ruby и большинство других основанных на классах ОО-языков, которые люди используют сегодня и которые имеют корневой класс, используют в Objectкачестве имени некоторые вариации, а не только Python.
abarnert

30

Да, это исторически . Без этого он создает класс в старом стиле.

Если вы используете type()объект старого стиля, вы просто получаете «экземпляр». На объекте нового стиля вы получаете его класс.


Кроме того, если вы используете type()класс старого стиля, вы получите «classobj» вместо «type».
Джоэл Шегрен

7

Синтаксис оператора создания класса:

class <ClassName>(superclass):
    #code follows

В отсутствие каких-либо других суперклассов, от которых вы конкретно хотите наследовать, superclassвсегда должно быть object, что является корнем всех классов в Python.

objectтехнически является корнем классов "нового стиля" в Python. Но классы нового стиля сегодня так же хороши, как и единственный стиль занятий.

Но если вы не используете слово явно objectпри создании классов, то, как уже упоминалось, Python 3.x неявно наследуется от objectсуперкласса. Но я думаю, что явное всегда лучше, чем неявное (ад)

Ссылка

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.