De ce clasele Python moștenesc obiectul?

Există vreun motiv pentru ca o declarație de clasă să moștenească de la object?

Tocmai am găsit un cod care face asta și nu găsesc un motiv bun pentru care.

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

person tjvr    schedule 25.10.2010    source sursă
comment
Aceasta creează o clasă în stil nou.   -  person SLaks    schedule 25.10.2010
comment
Răspunsul la această întrebare (deși simplu) este destul de greu de găsit. Googlarea lucrurilor precum clasa de bază a obiectelor Python sau similare vine cu pagini și pagini de tutoriale despre programarea orientată pe obiecte. Vot favorabil deoarece acesta este primul link care m-a condus la termenii de căutare obiecte python vechi vs. nou-stil   -  person vastlysuperiorman    schedule 22.12.2015
comment
Pentru a afla cum să căutați această întrebare, SymbolHound este o opțiune.   -  person user202729    schedule 31.01.2021


Răspunsuri (6)


Există vreun motiv pentru ca o declarație de clasă să moștenească de la object?

În Python 3, în afară de compatibilitatea dintre Python 2 și 3, niciun motiv. În Python 2, multe motive.


Povestea Python 2.x:

În Python 2.x (de la 2.2 în sus) există două stiluri de clase în funcție de prezența sau absența lui object ca clasă de bază:

  1. Clasele stil „clasic”: nu au object ca clasă de bază:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
    
  2. Clase de stil „nou”: au, direct sau indirect (de exemplu, moștenesc dintr-o tip încorporat), object ca clasă de bază:

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

Fără îndoială, atunci când scrii o clasă, vei dori întotdeauna să mergi la cursuri în stil nou. Avantajele de a face acest lucru sunt numeroase, pentru a enumera câteva dintre ele:

  • Suport pentru descriptori. În mod specific, următoarele constructe sunt posibile cu descriptori:

    1. classmethod: A method that receives the class as an implicit argument instead of the instance.
    2. staticmethod: o metodă care nu primește argumentul implicit self ca primă argument.
    3. proprietăți cu property: creați funcții pentru a gestiona obținerea, setarea și ștergerea un atribut.
    4. __slots__: salvează consumul de memorie al unei clase și, de asemenea, duce la un acces mai rapid la atribute . Desigur, impune limitări.
  • Metoda statică __new__: vă permite să personalizați modul în care sunt noile instanțe de clasă creată.

  • Ordinea de rezoluție a metodei (MRO): în ce ordine clasele de bază ale unei clase va fi căutat atunci când încercați să rezolvați ce metodă să apelați.

  • Legat de MRO, super apeluri. Consultați, de asemenea, super() considerat super.

Dacă nu moșteniți de la object, uitați de acestea. O descriere mai exhaustivă a punctelor anterioare, împreună cu alte avantaje ale claselor de stil „noi” poate fi găsită aici.

Unul dintre dezavantajele claselor de stil nou este că clasa în sine necesită mai multă memorie. Cu toate acestea, dacă nu creați multe obiecte de clasă, mă îndoiesc că aceasta ar fi o problemă și este o scufundare negativă într-o mare de aspecte pozitive.


Povestea Python 3.x:

În Python 3, lucrurile sunt simplificate. Există doar clase de stil nou (denumite în mod simplu clase), așa că singura diferență în adăugarea lui object este să vă cereți să introduceți încă 8 caractere. Acest:

class ClassicSpam:
    pass

este complet echivalent (în afară de numele lor :-) cu acesta:

class NewSpam(object):
     pass

si la asta:

class Spam():
    pass

Toți au object în __bases__.

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

Deci, ce ar trebui să faci?

În Python 2: moșteniți întotdeauna de la object în mod explicit. Obțineți beneficiile.

În Python 3: moșteniți din object dacă scrieți cod care încearcă să fie agnostic Python, adică trebuie să funcționeze atât în ​​Python 2, cât și în Python 3. În caz contrar, nu, nicio diferență, deoarece Python îl inserează pentru tine în spatele scenei.

person Dimitris Fasarakis Hilliard    schedule 12.07.2017
comment
în funcție de prezența sau absența unui tip încorporat ca clasă de bază =› de fapt nu este vorba despre absența sau prezența unui tip încorporat ca clasă de bază, ci despre faptul că clasa moștenește - direct sau indirect - de la object. IIRC a existat un moment în care nu toate tipurile încorporate au fost portate la clase de stil nou. - person bruno desthuilliers; 19.03.2018
comment
@brunodesthuilliers Impresia mea a fost că toate tipurile încorporate au moștenit de la object. Am un Python 2.2.3 și după o verificare rapidă nu am putut găsi un infractor, dar voi reformula răspunsul mai târziu pentru a fi mai clar. M-ar interesa totuși dacă ați găsi un exemplu, curiozitatea mea este stârnită. - person Dimitris Fasarakis Hilliard; 20.03.2018
comment
Cu toată sinceritatea (consultați IIRC în comentariul meu anterior) nu sunt 101% sigur despre acest punct (dacă toate tipurile încorporate au fost deja convertite în clase de stil nou când au fost introduse clase de stil nou) - s-ar putea să mă înșel, sau acest lucru ar fi putut viza doar unele dintre tipurile standard ale lib-ului (dar nu încorporate). Dar totuși, cred că ar trebui să fie mai bine să clarificăm că ceea ce face o clasă de stil nou este să aibă object în bazele sale. - person bruno desthuilliers; 20.03.2018
comment
staticmethod și classmethod funcționează bine chiar și la cursurile de stil vechi. property sorta funcționează pentru citire pe clase de stil vechi, pur și simplu nu reușește să intercepteze scrierile (deci dacă atribuiți numelui, instanța câștigă un atribut al numelui dat care umbrește proprietatea). De asemenea, rețineți că îmbunătățirea vitezei de acces la atribute de către __slots__ se referă în principal la anularea pierderii pe care o implică accesul la atribute de clasă de stil nou, deci nu este cu adevărat un punct de vânzare al claselor de stil nou (economiile de memorie sunt totuși un punct de vânzare). - person ShadowRanger; 02.04.2019

Python 3

  • class MyClass(object): = clasă în stil nou
  • class MyClass: = clasă în stil nou (moștenește implicit de la object)

Python 2

  • class MyClass(object): = clasă în stil nou
  • class MyClass: = CLASA DE STIL VECHI

Explicație:

Când definiți clase de bază în Python 3.x, aveți voie să eliminați object din definiție. Cu toate acestea, acest lucru poate deschide ușa pentru o problemă serios greu de urmărit...

Python a introdus clase de stil nou în Python 2.2, iar până acum clasele de stil vechi sunt într-adevăr destul de vechi. Discuția despre clasele în stil vechi este îngropată în cele 2 documente .x și inexistente în documentele 3.x.

Problema este că sintaxa pentru clasele în stil vechi în Python 2.x este aceeași cu sintaxa alternativă pentru clasele în stil nou în Python 3.x. Python 2.x este încă folosit pe scară largă (de exemplu, GAE, Web2Py), și orice cod (sau programator) care aduce fără să vrea definiții de clasă în stil 3.x în codul 2.x se va termina cu niște obiecte de bază serios învechite. Și pentru că cursurile în stil vechi nu sunt pe radarul nimănui, probabil că nu vor ști ce i-a lovit.

Așa că scrieți-l pe cale lungă și salvați lacrimile unor dezvoltatori 2.x.

person Yarin    schedule 25.02.2012
comment
Când definiți clase de bază în Python 3.x, aveți voie să eliminați obiectul din definiție. Cu toate acestea, acest lucru poate deschide ușa pentru o problemă serios greu de urmărit... La ce probleme vă referiți? - person Aidis; 11.12.2014
comment
@Aidis: Cred că înseamnă că codul care rulează atât pe Py2, cât și pe Py3 ar fi bine pe Py3, dar ar fi rupt pe Py2 dacă se bazează pe caracteristici de clasă de stil nou. Personal, dacă scriu cod așa, omit moștenirea explicită și pun doar __metaclass__ = type în partea de sus a modulului (după linia from __future__ import absolute_import, division, print_function :-) ); este un hack de compatibilitate în Py2 care face ca toate clasele definite ulterior în modul să fie în stil nou în mod implicit, iar în Py3, este complet ignorat (doar o variabilă globală aleatorie), așa că este inofensiv. - person ShadowRanger; 09.12.2016
comment
Acum că Python 2 este învechit, îi aruncați de pe orbită? - person endolith; 19.09.2020

Da, acesta este un obiect de „stil nou”. A fost o caracteristică introdusă în python2.2.

Obiectele de stil noi au un model de obiect diferit de obiectele clasice, iar unele lucruri nu vor funcționa corect cu obiectele de stil vechi, de exemplu, super(), @property și descriptori. Consultați acest articol pentru o descriere bună a ceea ce este nou clasa de stil este.

Link SO pentru o descriere a diferențelor: Care este diferența dintre stilul vechi și noi clase de stil în Python?

person Jerub    schedule 25.10.2010
comment
+1 asta. Rețineți că clasele în stil vechi au dispărut în Python 3, așa că trebuie doar să moșteniți de la object în Python 2. - person ; 25.10.2010
comment
Acesta nu este un răspuns real. Fac doar referire la alte articole. Cred că răspunsul lui Yarin ar trebui acceptat ca răspuns la această întrebare. - person alwbtc; 01.01.2016
comment
@alwbtc: Acest răspuns are și ceva nou. De exemplu, menționarea super() m-a condus la un altul important [aici](stackoverflow.com/questions/576169/ ). - person ViFI; 29.06.2016

Istoricul de la Învățați Python pe calea grea:

Redarea originală a unei clase de către Python a fost ruptă în multe moduri serioase. Până când a fost recunoscută această greșeală, era deja prea târziu și au trebuit să o susțină. Pentru a rezolva problema, aveau nevoie de un stil de „clasă nouă”, astfel încât „clasele vechi” să continue să funcționeze, dar puteți folosi noua versiune mai corectă.

Au decis că vor folosi un cuvânt „obiect”, cu litere mici, pentru a fi „clasa” de la care moștenești pentru a face o clasă. Este confuz, dar o clasă moștenește din clasa numită „obiect” pentru a face o clasă, dar nu este un obiect, de fapt, este o clasă, dar nu uitați să moșteniți de la obiect.

De asemenea, doar pentru a vă anunța care este diferența dintre clasele în stil nou și clasele în stil vechi, este că clasele în stil nou moștenesc întotdeauna de la clasa object sau de la o altă clasă care a moștenit de la object:

class NewStyle(object):
    pass

Un alt exemplu este:

class AnotherExampleOfNewStyle(NewStyle):
    pass

În timp ce o clasă de bază în stil vechi arată astfel:

class OldStyle():
    pass

Și o clasă pentru copii în stil vechi arată astfel:

class OldStyleSubclass(OldStyle):
    pass

Puteți vedea că o clasă de bază Old Style nu moștenește de la nicio altă clasă, totuși, clasele Old Style pot, desigur, să moștenească una de la alta. Moștenirea de la obiect garantează că anumite funcționalități sunt disponibile în fiecare clasă Python. Au fost introduse noi clase de stil în Python 2.2

person disp_name    schedule 04.11.2014
comment
Apelarea clasei rădăcină object nu este chiar atât de confuză și, de fapt, este destul de standard. Smalltalk are o clasă rădăcină numită Object și o metaclasă rădăcină numită Class. De ce? Pentru că, la fel cum Dog este o clasă pentru câini, Object este o clasă pentru obiecte, iar Class este o clasă pentru clase. Java, C#, ObjC, Ruby și majoritatea celorlalte limbaje OO bazate pe clasă pe care oamenii le folosesc astăzi și care au o clasă rădăcină folosesc o variație a Object ca nume, nu doar Python. - person abarnert; 04.05.2015

Da, este istoric. Fără el, se creează o clasă în stil vechi.

Dacă utilizați type() pe un obiect în stil vechi, obțineți doar „instanță”. Pe un obiect de stil nou obțineți clasa sa.

person knitti    schedule 25.10.2010
comment
De asemenea, dacă utilizați type() pe o clasă de stil vechi, obțineți classobj în loc de type. - person Joel Sjögren; 15.02.2014

Sintaxa instrucțiunii de creare a clasei:

class <ClassName>(superclass):
    #code follows

În absența oricăror alte superclase de la care doriți să moșteniți, superclass ar trebui să fie întotdeauna object, care este rădăcina tuturor claselor în Python.

object este din punct de vedere tehnic rădăcina claselor de „stil nou” în Python. Dar cursurile de tip nou de astăzi sunt la fel de bune ca fiind singurul stil de cursuri.

Dar, dacă nu folosiți în mod explicit cuvântul object atunci când creați clase, atunci, așa cum au menționat alții, Python 3.x moștenește implicit din superclasa object. Dar cred că explicit este întotdeauna mai bine decât implicit (la naiba)

Referință

person kmario23    schedule 20.10.2016