Klasa Python dziedziczy obiekt

1241

Czy istnieje powód, dla którego deklaracja klasy może dziedziczyć object?

Właśnie znalazłem kod, który to robi i nie mogę znaleźć dobrego powodu, dla którego to zrobiłbym.

class MyClass(object):
    # class code follows...
tjvr
źródło
2
To tworzy klasę w nowym stylu .
SLaks,
115
Odpowiedź na to pytanie (choć prosta) jest dość trudna do znalezienia. Googling, takie jak „klasa bazowa obiektów python” lub podobne, zawiera strony i strony samouczków na temat programowania obiektowego. Upvoting, ponieważ jest to pierwszy link, który doprowadził mnie do wyszukiwanych haseł „obiekty Python w starym lub nowym stylu”
ogromnie superormanalny

Odpowiedzi:

763

Czy istnieje powód, dla którego deklaracja klasy może dziedziczyć object?

W Pythonie 3, oprócz kompatybilności między Pythonem 2 i 3, nie ma powodu . W Python 2 wiele powodów .


Historia Python 2.x:

W Pythonie 2.x (od wersji 2.2) istnieją dwa style klas w zależności od obecności lub nieobecności objectjako klasy podstawowej:

  1. klasy „klasyczne” : nie mają objectjako klasy podstawowej:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
    
  2. „nowe” klasy stylów : mają, bezpośrednio lub pośrednio (np. dziedziczą po typie wbudowanym ), objectjako klasę podstawową:

    >>> 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'>,)
    

Bez wątpienia pisząc zajęcia, zawsze będziesz chciał iść na zajęcia w nowym stylu. Korzyści z tego są liczne, aby wymienić niektóre z nich:

  • Obsługa deskryptorów . W szczególności możliwe są następujące konstrukcje za pomocą deskryptorów:

    1. classmethod: Metoda, która odbiera klasę jako domyślny argument zamiast instancji.
    2. staticmethod: Metoda, która nie odbiera domyślnego argumentu selfjako pierwszego argumentu.
    3. właściwości z property: Utwórz funkcje do zarządzania uzyskiwaniem, ustawianiem i usuwaniem atrybutu.
    4. __slots__: Oszczędza zużycie pamięci przez klasę, a także skutkuje szybszym dostępem do atrybutów. Oczywiście nakłada ograniczenia .
  • Metoda __new__statyczna: pozwala dostosować sposób tworzenia nowych instancji klas.

  • Kolejność rozstrzygania metod (MRO) : w jakiej kolejności będą wyszukiwane klasy podstawowe klasy podczas próby rozstrzygnięcia, którą metodę wywołać.

  • Związane z MRO, superpołączenia . Zobacz także, super()uważane za super.

Jeśli nie dziedziczysz object, zapomnij o nich. Bardziej wyczerpujący opis poprzednich punktów wypunktowania wraz z innymi dodatkami „nowych” klas stylów można znaleźć tutaj .

Jedną z wad klas nowego stylu jest to, że sama klasa wymaga więcej pamięci. Chyba że tworzysz wiele obiektów klasowych, wątpię, by to był problem, a negatywne zatonięcie w morzu pozytywów.


Historia Python 3.x:

W Pythonie 3 rzeczy są uproszczone. Istnieją tylko klasy w nowym stylu (zwane po prostu klasami), więc jedyną różnicą w dodawaniu objectjest wymaganie wpisania kolejnych 8 znaków. To:

class ClassicSpam:
    pass

jest całkowicie równoważne (oprócz ich nazwy :-) z tym:

class NewSpam(object):
     pass

i do tego:

class Spam():
    pass

Wszystkie mają objectw sobie __bases__.

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

Co powinieneś zrobić?

W Python 2: zawsze dziedzicz po objectjawnie . Zdobądź profity.

W Pythonie 3: dziedzicz, objectjeśli piszesz kod, który próbuje być agnostyczny w Pythonie, to znaczy musi działać zarówno w Pythonie 2, jak i Pythonie 3. W przeciwnym razie nie robi to żadnej różnicy, ponieważ Python wstawia go dla Ciebie za kulisami.

Dimitris Fasarakis Hilliard
źródło
„w zależności od obecności lub braku wbudowanego typu jako klasy bazowej” => w rzeczywistości nie chodzi o „brak lub obecność wbudowanego typu jako klasy bazowej”, ale o to, czy klasa dziedziczy - bezpośrednio lub pośrednio - od object. IIRC był moment, w którym nie wszystkie wbudowane typy zostały przeniesione do klas nowego stylu.
bruno desthuilliers
@brunodesthuilliers Mam wrażenie, że wszystkie wbudowane typy odziedziczyły object. Mam już Python 2.2.3 i po szybkim sprawdzeniu nie mogłem znaleźć przestępcy, ale przeredaguję odpowiedź później, aby była bardziej przejrzysta. Byłbym zainteresowany, gdybyś mógł znaleźć przykład, moja ciekawość jest rozbudzona.
Dimitris Fasarakis Hilliard
Szczerze mówiąc (por. „IIRC” w moim poprzednim komentarzu) nie jestem w 101% pewien co do tego punktu (czy wszystkie typy wbudowane zostały już przekonwertowane na klasy w nowym stylu, gdy wprowadzono klasy w nowym stylu) - może po prostu jestem prosty źle, lub mogło to dotyczyć tylko niektórych standardowych typów bibliotek (ale nie wbudowanych). Ale myślę, że lepiej jest wyjaśnić, że to, co czyni klasę nowego stylu, ma objectswoje podstawy.
bruno desthuilliers
7
szkoda, że ​​stackoverflow robi tylko upvote = upvote + 1 dla tych rodzajów odpowiedzi, chciałbym móc zrobić upvote + = N
PirateApp
1
staticmethodi classmethoddziała dobrze nawet na lekcjach w starym stylu. propertySorta działa do odczytu klas starego stylu, po prostu nie przechwytuje zapisów (więc jeśli przypiszesz do nazwy, instancja otrzymuje atrybut o podanej nazwie, który przesłania właściwość). Zauważ też, że __slots__poprawa szybkości dostępu do atrybutu polega głównie na usunięciu straty, jaką ponosi dostęp do atrybutu klasy w nowym stylu, więc nie jest to tak naprawdę zaletą klas nowego stylu (jednak oszczędność pamięci jest zaletą).
ShadowRanger
540

Python 3

  • class MyClass(object): = Klasa w nowym stylu
  • class MyClass:= Klasa w nowym stylu (domyślnie dziedziczy po object)

Python 2

  • class MyClass(object): = Klasa w nowym stylu
  • class MyClass:= KLASA STYLU

Objaśnienie :

Podczas definiowania klas podstawowych w Pythonie 3.x możesz usunąć objectdefinicję. Może to jednak otworzyć drzwi dla poważnie trudnego do wyśledzenia problemu…

Python wprowadził klasy nowego stylu w Pythonie 2.2, a teraz klasy starego stylu są naprawdę dość stare. Dyskusja na temat klas w starym stylu jest zakopana w dokumentach 2.x , a nie istnieje w dokumentach 3.x.

Problemem jest to, składnia klas starym stylu w Pythonie 2.x jest taka sama jak w alternatywnej składni dla klas nowego stylu w Pythonie 3.x . Python 2.x jest nadal bardzo szeroko stosowany (np. GAE, Web2Py), a każdy kod (lub koder) nieświadomie przenoszący definicje klas w stylu 3.x do kodu 2.x skończy się z poważnie nieaktualnymi obiektami podstawowymi. A ponieważ zajęcia w starym stylu nie są niczyje na radarach, prawdopodobnie nie będą wiedzieć, co ich uderzyło.

Po prostu przeliteruj to i ocal łzy jakiegoś programisty w wersji 2.x.

Yarin
źródło
13
„Definiując klasy podstawowe w Pythonie 3.x, możesz usunąć obiekt z definicji. Może to jednak otworzyć drzwi dla poważnie trudnego do śledzenia problemu…” Jakie problemy masz na myśli?
Aidis,
6
@Aidis: Myślę, że mają na myśli, że kod działający zarówno na Py2, jak i Py3 byłby odpowiedni na Py3, ale zostałby zepsuty na Py2, jeśli opiera się na funkcjach klasy w nowym stylu. Osobiście, jeśli piszę taki kod, pomijam jawne dziedziczenie i po prostu umieszczam __metaclass__ = typena górze modułu (po from __future__ import absolute_import, division, print_functionwierszu :-)); jest to hack kompatybilności w Py2, który domyślnie sprawia, że ​​wszystkie później zdefiniowane klasy w module są w nowym stylu, aw Py3 jest całkowicie ignorowany (tylko losowa zmienna globalna siedząca w pobliżu), więc jest nieszkodliwy.
ShadowRanger
400

Tak, jest to obiekt „nowego stylu”. To była funkcja wprowadzona w python2.2.

Nowe obiekty mają inny styl obiektowy model do klasycznych obiektów, a niektóre rzeczy nie będzie działać poprawnie ze starymi obiektami typu, na przykład super(), @propertyi deskryptorów. Zobacz ten artykuł, aby uzyskać dobry opis tego, czym jest nowa klasa stylu.

SO link do opisu różnic: Jaka jest różnica między starymi stylami a nowymi klasami stylów w Pythonie?

Jerub
źródło
110
+1 to. Zauważ, że w Pythonie 3 nie ma klas starego stylu, więc musisz dziedziczyć tylko objectw Pythonie 2.
9
To nie jest prawdziwa odpowiedź. po prostu podaje odniesienia do innych artykułów. Myślę, że odpowiedź Yarina powinna zostać zaakceptowana jako odpowiedź na to pytanie.
alwbtc
2
@alwbtc: Ta odpowiedź też ma coś nowego. Na przykład wzmianka o „super ()” doprowadziła mnie do innego ważnego [tutaj] ( stackoverflow.com/questions/576169/… ).
ViFI
34

Historia z Dowiedz się Python na własnej skórze :

Oryginalna interpretacja klasy Pythona została złamana na wiele poważnych sposobów. Gdy ta wada została rozpoznana, było już za późno i musieli ją wesprzeć. Aby rozwiązać problem, potrzebowali stylu „nowej klasy”, aby „stare klasy” nadal działały, ale można użyć nowej, bardziej poprawnej wersji.

Zdecydowali, że użyją słowa „obiekt”, małe litery, aby być „klasą”, po której odziedziczysz klasę. Jest to mylące, ale klasa dziedziczy po klasie o nazwie „obiekt”, aby utworzyć klasę, ale tak naprawdę nie jest to obiekt, to klasa, ale nie zapomnij dziedziczyć po obiekcie.

Również po to, abyś wiedział, jaka jest różnica między klasami w nowym stylu a klasami w starym stylu, jest tak, że klasy w nowym stylu zawsze dziedziczą po objectklasie lub innej klasie, która odziedziczyła po object:

class NewStyle(object):
    pass

Innym przykładem jest:

class AnotherExampleOfNewStyle(NewStyle):
    pass

Podczas gdy klasa podstawowa w starym stylu wygląda tak:

class OldStyle():
    pass

A klasa dla dzieci w starym stylu wygląda następująco:

class OldStyleSubclass(OldStyle):
    pass

Widać, że klasa podstawowa Old Style nie dziedziczy po żadnej innej klasie, jednak klasy Old Style mogą oczywiście dziedziczyć po sobie. Dziedziczenie po obiekcie gwarantuje, że określona funkcjonalność jest dostępna w każdej klasie Python. W Python 2.2 wprowadzono nowe klasy stylów

nazwa_wyświetlacza
źródło
8
Wywołanie klasy root objectnie jest aż tak mylące, a tak naprawdę jest dość standardowe. Smalltalk ma klasę root o nazwie Objecti metaklasę root o nazwie Class. Dlaczego? Ponieważ, podobnie jak Dogklasa dla psów, Objectjest klasą dla przedmiotów i Classklasą dla klas. Java, C #, ObjC, Ruby i większość innych opartych na klasach języków OO, które ludzie używają dzisiaj i którzy mają klasę root, używają różnych odmian Objectjako nazwy, nie tylko Pythona.
abarnert
30

Tak, to jest historyczne . Bez tego tworzy klasę w starym stylu.

Jeśli używasz obiektu type()w starym stylu, dostajesz po prostu „instancję”. Na obiekcie w nowym stylu dostajesz jego klasę.

knitti
źródło
Ponadto, jeśli korzystasz type()z klas w starym stylu, zamiast „pisz” dostajesz „classobj”.
Joel Sjögren
7

Składnia instrukcji tworzenia klasy:

class <ClassName>(superclass):
    #code follows

W przypadku braku innych superklas, które konkretnie chcesz dziedziczyć, superclasszawsze powinno być object, co jest rdzeniem wszystkich klas w Pythonie.

objectjest technicznie głównym źródłem klas „nowego stylu” w Pythonie. Ale dziś klasy w nowym stylu są tak dobre, jak jedyny styl zajęć.

Ale jeśli nie użyjesz tego słowa wprost objectpodczas tworzenia klas, to jak wspomniano inni, Python 3.x domyślnie dziedziczy po objectnadklasie. Ale chyba jawne jest zawsze lepsze niż niejawne (piekło)

Odniesienie

kmario23
źródło