Почему классы Python наследуют объект?

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

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

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

person tjvr    schedule 25.10.2010    source источник
comment
Это создает класс нового стиля.   -  person SLaks    schedule 25.10.2010
comment
Ответ на этот вопрос (пока простой) найти довольно сложно. При поиске в Google таких вещей, как базовый класс объекта python или аналогичные, появляются страницы и страницы руководств по объектно-ориентированному программированию. Голосование за, потому что это первая ссылка, которая привела меня к поисковым запросам старых и новых объектов Python   -  person vastlysuperiorman    schedule 22.12.2015
comment
Чтобы узнать, как искать эту часть вопроса, SymbolHound - это вариант.   -  person user202729    schedule 31.01.2021


Ответы (6)


Есть ли причина для наследования класса от 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: A method that receives the class as an implicit argument instead of the instance.
    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 вставляет его за кулисами.

person Dimitris Fasarakis Hilliard    schedule 12.07.2017
comment
в зависимости от наличия или отсутствия встроенного типа в качестве базового класса = ›на самом деле речь идет не об отсутствии или наличии встроенного типа в качестве базового класса, а в том, наследует ли класс - прямо или косвенно - от 1_. IIRC был момент времени, когда еще не все встроенные типы были перенесены в классы нового стиля. - person bruno desthuilliers; 19.03.2018
comment
@brunodesthuilliers У меня сложилось впечатление, что все встроенные типы действительно унаследованы от object. У меня есть Python 2.2.3, и после быстрой проверки я не смог найти нарушителя, но позже я перефразирую ответ, чтобы сделать его более понятным. Было бы интересно, если бы вы могли найти пример, мое любопытство задето. - person Dimitris Fasarakis Hilliard; 20.03.2018
comment
Честно говоря (см. IIRC в моем предыдущем комментарии), я не уверен на 101% в этом вопросе (все ли встроенные типы уже были преобразованы в классы нового стиля, когда были введены классы нового стиля) - я могу просто ошибаться, или это могло касаться только некоторых стандартных типов библиотеки (но не встроенных). Но все же я думаю, что лучше уточнить, что делает класс нового стиля object в его основе. - person bruno desthuilliers; 20.03.2018
comment
staticmethod и classmethod прекрасно работают даже в классах старого стиля. property sorta работает для чтения в классах старого стиля, она просто не может перехватывать записи (поэтому, если вы присваиваете имя, экземпляр получает атрибут данного имени, который затеняет свойство). Также обратите внимание, что улучшение __slots__ в скорости доступа к атрибутам в основном связано с устранением потерь, которые несет доступ к атрибутам класса нового стиля, поэтому на самом деле это не является преимуществом для классов нового стиля (хотя экономия памяти - это аргумент в пользу продажи). - person ShadowRanger; 02.04.2019

Python 3

  • class MyClass(object): = Класс нового стиля
  • class MyClass: = класс нового стиля (неявно наследуется от object)

Python 2

  • class MyClass(object): = Класс нового стиля
  • class MyClass: = КЛАСС СТАРОГО СТИЛЯ

Объяснение:

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

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

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

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

person Yarin    schedule 25.02.2012
comment
При определении базовых классов в Python 3.x вы можете удалить объект из определения. Однако это может открыть дверь для серьезной проблемы, которую трудно отследить… Какие проблемы вы имеете в виду? - person Aidis; 11.12.2014
comment
@Aidis: Я думаю, они имеют в виду, что код, который работает как на Py2, так и на Py3, будет хорошо работать на Py3, но не будет работать на Py2, если он полагается на функции класса нового стиля. Лично, если я пишу такой код, я опускаю явное наследование и просто помещаю __metaclass__ = type в верхней части модуля (после строки from __future__ import absolute_import, division, print_function :-)); это хак совместимости в Py2, который делает все впоследствии определенные классы в модуле новым стилем по умолчанию, а в Py3 он полностью игнорируется (просто случайная глобальная переменная), поэтому он безвреден. - person ShadowRanger; 09.12.2016
comment
Теперь, когда Python 2 устарел, уничтожить их с орбиты? - person endolith; 19.09.2020

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

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

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

person Jerub    schedule 25.10.2010
comment
+1 Это. Обратите внимание, что классы старого стиля исчезли в Python 3, поэтому вам нужно только наследовать от object в Python 2. - person ; 25.10.2010
comment
Это не настоящий ответ. Я просто даю ссылки на другие статьи. Думаю, ответ Ярина следует принять как ответ на этот вопрос. - person alwbtc; 01.01.2016
comment
@alwbtc: В этом ответе тоже есть кое-что новое. Например, упоминание super () привело меня к другому важному [здесь] (stackoverflow.com/questions/576169/). - person ViFI; 29.06.2016

История из усердного изучения Python:

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

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

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

class NewStyle(object):
    pass

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

class AnotherExampleOfNewStyle(NewStyle):
    pass

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

class OldStyle():
    pass

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

class OldStyleSubclass(OldStyle):
    pass

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

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

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

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

person knitti    schedule 25.10.2010
comment
Кроме того, если вы используете type() в классе старого стиля, вы получите classobj вместо type. - person Joel Sjögren; 15.02.2014

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

class <ClassName>(superclass):
    #code follows

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

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

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

Справочник

person kmario23    schedule 20.10.2016