Клас Python успадковує об'єкт


1241

Чи є причина для успадкування декларації класу object?

Я просто знайшов якийсь код, який робить це, і я не можу знайти вагому причину.

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


115
Відповідь на це питання (хоча просто) знайти досить складно. Гуглінг таких речей, як "базовий клас об'єктів python" або подібних, створює сторінки та сторінки навчальних посібників з об'єктно-орієнтованого програмування. Оновлення, оскільки це перше посилання, яке привело мене до пошукових термінів "старі об'єкти python в новому стилі"
значно перевершений

Відповіді:


763

Чи є причина для успадкування декларації класу 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) : в якому порядку будуть шукати базові класи класу при спробі вирішити, який метод викликати.

  • Пов’язані з МРО, 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 був момент часу, коли ще не всі вбудовані типи, де перенесені до класів нового стилю.
bruno desthuilliers

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

Чесно кажучи (див. "IIRC" у моєму попередньому коментарі), я не впевнений у цьому питанні на 101% (чим раніше усі вбудовані типи були перетворені на класи нового стилю, коли були запроваджені класи нового стилю) - я можу бути просто зрозумілим неправильно, або це може стосуватися лише деяких стандартних типів ліб (але не вбудованих). Але все ж я думаю, що слід краще уточнити, що те, що створює клас нового стилю, полягає objectв його базах.
bruno desthuilliers

7
занадто поганий stackoverflow робить лише upvote = upvote + 1 для цих своєрідних відповідей, я б хотів, щоб я міг upvote + = N
PirateApp

1
staticmethodі classmethodдобре працювати навіть на уроках старого стилю. propertysorta працює для читання на класах старого стилю, вона просто не перехоплює записи (тому, якщо ви присвоїте ім'я, екземпляр отримує атрибут заданого імені, що затінює властивість). Також зауважте, що __slots__поліпшення швидкості доступу до атрибутів пов'язане здебільшого з того, щоб скасувати втрату, яку зазнає доступ до атрибутів класу нового стилю, тому це насправді не продажа класів нового стилю (хоча економія пам’яті є точкою продажу).
ShadowRanger

540

Пітон 3

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

Пітон 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та дескрипторами. Дивіться цю статтю для хорошого опису того, що таке новий клас стилів.

SO-посилання для опису відмінностей: Яка різниця між старим стилем та класами нового стилю в Python?


110
+1 Це. Зауважте, що класи в старому стилі відсутні в Python 3, тому вам потрібно успадкувати лише objectв Python 2.

9
Це не справжня відповідь. Я просто посилається на інші статті. Я думаю, що відповідь Яріна слід сприймати як відповідь на це питання.
alwbtc

2
@alwbtc: У цій відповіді є щось нове. Наприклад, згадка про "super ()" привела мене до іншого важливого [тут] ( stackoverflow.com/questions/576169/… ).
ViFI

34

Історія з Learn Python the Hard Way :

Первісне передання класу Python було порушено багатьма серйозними способами. На той момент, коли цю провину було визнано, вже було пізно, і вони повинні були її підтримати. Для усунення проблеми їм знадобився деякий стиль "нового класу", щоб "старі класи" продовжували працювати, але ви можете використовувати нову більш правильну версію.

Вони вирішили, що будуть використовувати слово "об'єкт" з нижнього регістру, щоб бути "класом", від якого ви успадковуєте, щоб створити клас. Це заплутано, але клас успадковує від класу, який називається "об'єкт", щоб зробити клас, але це не об'єкт насправді його клас, але не забудьте успадкувати від об'єкта.

Крім того, щоб дізнатися, у чому різниця між класами нового стилю та класами старого стилю, це те, що класи нового стилю завжди успадковують від objectкласу або від іншого класу, який успадкував від object:

class NewStyle(object):
    pass

Інший приклад:

class AnotherExampleOfNewStyle(NewStyle):
    pass

Хоча базовий клас у старому стилі виглядає так:

class OldStyle():
    pass

І дитячий клас у старому стилі виглядає так:

class OldStyleSubclass(OldStyle):
    pass

Видно, що базовий клас Old Style не успадковує жоден інший клас, однак класи Old Style можуть, звичайно, успадковувати один одного. Спадкування від об'єкта гарантує, що певна функціональність доступна в кожному класі Python. Нові класи стилів були введені в Python 2.2


8
Виклик кореневого класу objectне все так заплутано, а насправді це досить стандартно. У Smalltalk є кореневий клас з іменем Objectта кореневий метаклас з назвою Class. Чому? Тому що, як Dogі клас для собак, Objectце клас для предметів, і Classце клас для занять. Java, C #, ObjC, Ruby та більшість інших мов на базі класу OO, якими користуються люди сьогодні, які мають кореневий клас, використовують деякі варіанти Objectяк імені, а не лише Python.
abarnert

30

Так, це історично . Без нього він створює клас у старому стилі.

Якщо ви використовуєте type()об’єкт у старому стилі, ви просто отримаєте "екземпляр". На новому стилі ви отримуєте його клас.


Крім того, якщо ви користуєтесь type()класом старого стилю, ви отримуєте "classobj" замість "type".
Joel Sjögren

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.