Dlaczego klasy Pythona dziedziczą obiekt?

Czy jest jakiś powód, dla którego deklaracja klasy ma dziedziczyć z object?

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

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

person tjvr    schedule 25.10.2010    source źródło
comment
Spowoduje to utworzenie klasy nowego stylu.   -  person SLaks    schedule 25.10.2010
comment
Odpowiedź na to pytanie (choć prosta) jest dość trudna do znalezienia. Googlowanie rzeczy, takich jak klasa bazowa obiektów Pythona lub podobne, powoduje pojawienie się stron i stron samouczków dotyczących programowania obiektowego. Głosowanie, ponieważ jest to pierwszy link, który doprowadził mnie do wyszukiwanych haseł obiektów Pythona w starym i nowym stylu   -  person vastlysuperiorman    schedule 22.12.2015
comment
Aby dowiedzieć się, jak wyszukać tę część pytania, SymbolHound jest opcją.   -  person user202729    schedule 31.01.2021


Odpowiedzi (6)


Czy jest jakiś powód, dla którego deklaracja klasy ma dziedziczyć z object?

W Pythonie 3, poza kompatybilnością między Pythonem 2 i 3, bez powodu. W Pythonie 2 wiele powodów.


Historia Pythona 2.x:

W Pythonie 2.x (od 2.2 i nowszych) istnieją dwa style klas w zależności od obecności lub nieobecności object jako klasy bazowej:

  1. Klasy w stylu „klasycznym”: nie mają klasy object jako klasy bazowej:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
    
  2. „nowe” klasy stylu: mają bezpośrednio lub pośrednio (np. dziedziczą z typ wbudowany), object jako klasa bazowa:

    >>> 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ł wybrać 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 z deskryptorami:

    1. classmethod: A method that receives the class as an implicit argument instead of the instance.
    2. staticmethod: metoda, która jako pierwsza nie otrzymuje niejawnego argumentu self argument.
    3. właściwości z property: Utwórz funkcje do zarządzania pobieraniem, ustawianiem i usuwaniem atrybut.
    4. __slots__: oszczędza zużycie pamięci przez klasę, a także zapewnia szybszy dostęp do atrybutów . Oczywiście nakłada ograniczenia.
  • Metoda statyczna __new__: pozwala dostosować sposób, w jaki są nowe wystąpienia klas Utworzony.

  • Kolejność rozwiązywania metod (MRO): w jakiej kolejności klasy bazowe klasy będą przeszukiwane podczas próby określenia, którą metodę należy wywołać.

  • Powiązane z MRO, super wywołania. Zobacz też, super() uważane za super.

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

Jedną z wad klas w nowym stylu jest to, że sama klasa jest bardziej wymagająca pamięci. Jeśli jednak nie tworzysz wielu obiektów klasowych, wątpię, aby stanowiło to problem i jest to negatywne zatonięcie w morzu pozytywów.


Historia Pythona 3.x:

W Pythonie 3 rzeczy są uproszczone. Istnieją tylko klasy w nowym stylu (określane po prostu jako klasy), więc jedyną różnicą w dodawaniu object jest konieczność wpisania 8 dodatkowych znaków. Ten:

class ClassicSpam:
    pass

jest całkowicie równoważny (poza nazwą :-) z tym:

class NewSpam(object):
     pass

i do tego:

class Spam():
    pass

Wszyscy mają object w swoim __bases__.

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

Więc co powinieneś zrobić?

W Pythonie 2: zawsze dziedzicz wyraźnie po object. Zdobądź korzyści.

W Pythonie 3: dziedzicz z object, jeśli piszesz kod, który stara się być niezależny od Pythona, to znaczy, że musi działać zarówno w Pythonie 2, jak i w Pythonie 3. W przeciwnym razie nie rób tego, to naprawdę sprawia, że nie ma różnicy, ponieważ Python wstawia go za kulisami.

person Dimitris Fasarakis Hilliard    schedule 12.07.2017
comment
w zależności od obecności lub nieobecności typu wbudowanego jako klasy bazowej =› właściwie nie chodzi o brak lub obecność typu wbudowanego jako klasy bazowej, ale czy klasa dziedziczy - bezpośrednio lub pośrednio - od 1_. IIRC był moment, w którym nie wszystkie typy wbudowane zostały jeszcze przeniesione do klas nowego stylu. - person bruno desthuilliers; 19.03.2018
comment
@brunodesthuilliers Odniosłem wrażenie, że wszystkie typy wbudowane dziedziczą po object. Mam wokół Pythona 2.2.3 i po szybkim sprawdzeniu nie mogłem znaleźć przestępcy, ale przeredaguję odpowiedź później, aby była bardziej jasna. Byłbym zainteresowany, gdybyś mógł znaleźć przykład, ale moja ciekawość jest rozbudzona. - person Dimitris Fasarakis Hilliard; 20.03.2018
comment
Z całą szczerością (por. IIRC w moim poprzednim komentarzu) nie jestem w 101% pewien 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 się mylę, lub może to dotyczyć tylko niektórych typów standardowych lib (ale nie wbudowanych). Ale myślę, że lepiej byłoby wyjaśnić, że to, co sprawia, że ​​klasa w nowym stylu, to posiadanie object w swoich podstawach. - person bruno desthuilliers; 20.03.2018
comment
staticmethod i classmethod działają dobrze nawet na zajęciach w starym stylu. property sorta działa do odczytu na klasach w starym stylu, po prostu nie przechwytuje zapisów (więc jeśli przypiszesz do nazwy, instancja zyskuje atrybut podanej nazwy, który zasłania właściwość). Należy również zauważyć, że ulepszenie __slots__ w zakresie szybkości dostępu do atrybutów polega głównie na cofnięciu straty, jaką ponosi dostęp do atrybutów klas w nowym stylu, więc nie jest to tak naprawdę zaleta klas w nowym stylu (jednak oszczędność pamięci jest zaletą). - person ShadowRanger; 02.04.2019

Python 3

  • class MyClass(object): = Klasa w nowym stylu
  • class MyClass: = Klasa w nowym stylu (niejawnie dziedziczy z object)

Python 2

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

Wyjaśnienie:

Definiując klasy bazowe w Pythonie 3.x, możesz usunąć object z definicji. Może to jednak otworzyć drzwi do naprawdę trudnego do wyśledzenia problemu…

Python wprowadził klasy w nowym stylu z powrotem w Pythonie 2.2, a obecnie klasy w starym stylu są naprawdę bardzo stare. Dyskusja o klasach w starym stylu jest pogrzebana w 2 Dokumenty .x i nie istnieją w dokumentacji 3.x.

Problem polega na tym, że składnia klas w starym stylu w Pythonie 2.x jest taka sama jak alternatywna składnia klas w nowym stylu w Pythonie 3.x. Python 2.x jest nadal bardzo powszechnie używany (np. GAE, Web2Py), a każdy kod (lub koder), który nieświadomie wprowadza definicje klas w stylu 3.x do kodu 2.x, będzie miał bardzo przestarzałe obiekty bazowe. A ponieważ zajęcia w starym stylu nie są nikomu na celowniku, prawdopodobnie nie będą wiedzieć, co ich uderzyło.

Więc po prostu przeliteruj to z daleka i oszczędź łzom programistom 2.x.

person Yarin    schedule 25.02.2012
comment
Podczas definiowania klas bazowych w Pythonie 3.x możesz usunąć obiekt z definicji. Może to jednak otworzyć drzwi do naprawdę trudnego do wyśledzenia problemu… Do jakich problemów się odnosisz? - person Aidis; 11.12.2014
comment
@Aidis: Myślę, że mają na myśli, że kod działający zarówno na Py2, jak i Py3 byłby w porządku na Py3, ale byłby zepsuty na Py2, jeśli opiera się na funkcjach klas w nowym stylu. Osobiście, jeśli piszę taki kod, pomijam jawne dziedziczenie i po prostu umieszczam __metaclass__ = type na górze modułu (po linii from __future__ import absolute_import, division, print_function :-) ); jest to hack kompatybilności w Py2, który sprawia, że ​​wszystkie później zdefiniowane klasy w module są domyślnie w nowym stylu, a w Py3 jest to całkowicie ignorowane (po prostu losowa zmienna globalna, która znajduje się wokół), więc jest nieszkodliwa. - person ShadowRanger; 09.12.2016
comment
Teraz, gdy Python 2 jest przestarzały, wystrzelić je z orbity? - person endolith; 19.09.2020

Tak, to jest obiekt w „nowym stylu”. Była to funkcja wprowadzona w Pythonie2.2.

Obiekty w nowym stylu mają inny model obiektów niż obiekty klasyczne, a niektóre rzeczy nie będą działać poprawnie z obiektami w starym stylu, na przykład super(), @property i deskryptory. Zapoznaj się z tym artykułem, aby uzyskać dobry opis nowości klasa stylu to.

SO link do opisu różnic: Jaka jest różnica między starym stylem i nowe klasy stylów w Pythonie?

person Jerub    schedule 25.10.2010
comment
+1 to. Zauważ, że klasy w starym stylu zniknęły w Pythonie 3, więc wystarczy dziedziczyć po object w Pythonie 2. - person ; 25.10.2010
comment
To nie jest prawdziwa odpowiedź. Podaję tylko odniesienia do innych artykułów. Myślę, że odpowiedź Yarina należy przyjąć jako odpowiedź na to pytanie. - person alwbtc; 01.01.2016
comment
@alwbtc : Ta odpowiedź też ma coś nowego. Na przykład wzmianka o super() doprowadziła mnie do innej ważnej [tutaj](stackoverflow.com/questions/576169/ ). - person ViFI; 29.06.2016

Historia z Naucz się Pythona w trudny sposób:

Oryginalna wersja klasy Pythona została zepsuta na wiele poważnych sposobów. Do czasu rozpoznania tej wady było już za późno i musieli ją poprzeć. Aby rozwiązać ten problem, potrzebowali stylu „nowej klasy”, aby „stare klasy” nadal działały, ale możesz użyć nowej, bardziej poprawnej wersji.

Zdecydowali, że użyją słowa „obiekt”, pisanego małymi literami, jako „klasy”, z której dziedziczysz, aby utworzyć klasę. Jest to mylące, ale klasa dziedziczy po klasie o nazwie „object”, aby utworzyć klasę, ale nie jest to obiekt, tak naprawdę jest to klasa, ale nie zapomnij dziedziczyć po obiekcie.

Również po to, aby poinformować Cię, jaka jest różnica między klasami w nowym stylu a klasami w starym stylu, jest to, że klasy w nowym stylu zawsze dziedziczą z klasy object lub z innej klasy, która dziedziczyła z klasy object:

class NewStyle(object):
    pass

Innym przykładem jest:

class AnotherExampleOfNewStyle(NewStyle):
    pass

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

class OldStyle():
    pass

A klasa potomna w starym stylu wygląda tak:

class OldStyleSubclass(OldStyle):
    pass

Widać, że klasa bazowa w starym stylu nie dziedziczy po żadnej innej klasie, jednak klasy w starym stylu mogą oczywiście dziedziczyć po sobie nawzajem. Dziedziczenie z obiektu gwarantuje, że określona funkcjonalność jest dostępna w każdej klasie Pythona. Nowe klasy stylów zostały wprowadzone w Pythonie 2.2

person disp_name    schedule 04.11.2014
comment
Wywołanie klasy głównej object nie jest aż tak mylące iw rzeczywistości jest dość standardowe. Smalltalk ma klasę główną o nazwie Object i metaklasę główną o nazwie Class. Czemu? Ponieważ tak jak Dog jest klasą dla psów, Object jest klasą dla obiektów, a Class jest klasą dla klas. Java, C#, ObjC, Ruby i większość innych języków OO opartych na klasach, których ludzie używają dzisiaj, a które mają klasę główną, używają jakiejś odmiany Object jako nazwy, a nie tylko Pythona. - person abarnert; 04.05.2015

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

Jeśli użyjesz type() na obiekcie w starym stylu, otrzymasz po prostu „instancję”. Na obiekcie w nowym stylu otrzymujesz jego klasę.

person knitti    schedule 25.10.2010
comment
Ponadto, jeśli użyjesz type() na klasie w starym stylu, otrzymasz classobj zamiast type. - person Joel Sjögren; 15.02.2014

Składnia instrukcji tworzenia klasy:

class <ClassName>(superclass):
    #code follows

W przypadku braku innych nadklas, z których konkretnie chcesz dziedziczyć, superclass powinna zawsze mieć wartość object, która jest korzeniem wszystkich klas w Pythonie.

object to technicznie podstawa klas „nowego stylu” w Pythonie. Ale dzisiejsze zajęcia w nowym stylu są tak dobre, jak bycie jedynym stylem zajęć.

Ale jeśli nie użyjesz wyraźnie słowa object podczas tworzenia klas, to jak wspomnieli inni, Python 3.x niejawnie dziedziczy z nadklasy object. Ale myślę, że wyraźny jest zawsze lepszy niż ukryty (piekło)

Informacje

person kmario23    schedule 20.10.2016