C'è qualche motivo per cui una dichiarazione di classe erediti object
?
Ho appena trovato un codice che lo fa e non riesco a trovare una buona ragione per cui.
class MyClass(object):
# class code follows...
C'è qualche motivo per cui una dichiarazione di classe erediti object
?
Ho appena trovato un codice che lo fa e non riesco a trovare una buona ragione per cui.
class MyClass(object):
# class code follows...
Risposte:
C'è qualche motivo per cui una dichiarazione di classe erediti
object
?
In Python 3, a parte la compatibilità tra Python 2 e 3, nessun motivo . In Python 2, molte ragioni .
In Python 2.x (dalla versione 2.2 in poi) ci sono due stili di classi a seconda della presenza o assenza di object
come classe base:
Classi di stile "classico" : non hanno object
come classe di base:
>>> class ClassicSpam: # no base class
... pass
>>> ClassicSpam.__bases__
()
"nuove" classi di stile : hanno, direttamente o indirettamente (ad esempio ereditare da un tipo incorporato ), object
come classe di base:
>>> 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'>,)
Senza dubbio, quando scrivi una classe ti consigliamo sempre di seguire lezioni di nuovo stile. I vantaggi di farlo sono numerosi, per elencarne alcuni:
Supporto per descrittori . In particolare, i seguenti costrutti sono resi possibili con i descrittori:
classmethod
: Un metodo che riceve la classe come argomento implicito anziché l'istanza.staticmethod
: Un metodo che non riceve l'argomento implicito self
come primo argomento.property
: Crea funzioni per gestire l'ottenimento, l'impostazione e l'eliminazione di un attributo.__slots__
: Salva i consumi di memoria di una classe e consente anche un accesso più rapido agli attributi. Certo, impone limiti .Il __new__
metodo statico: consente di personalizzare la modalità di creazione delle nuove istanze di classe.
Ordine di risoluzione del metodo (MRO) : in quale ordine verranno ricercate le classi base di una classe quando si cerca di risolvere quale metodo chiamare.
Relativo a MRO, super
chiamate . Vedi anche, super()
considerato super.
Se non erediti object
, dimentica questi. Una descrizione più esaustiva dei punti elenco precedenti insieme ad altri vantaggi di "nuove" classi di stile è disponibile qui .
Uno degli svantaggi delle classi di nuovo stile è che la classe stessa richiede più memoria. A meno che tu non stia creando molti oggetti di classe, dubito che questo sarebbe un problema ed è un affondamento negativo in un mare di aspetti positivi.
In Python 3, le cose sono semplificate. Esistono solo classi di nuovo stile (definite chiaramente come classi), quindi l'unica differenza nell'aggiunta object
è la necessità di digitare altri 8 caratteri. Questo:
class ClassicSpam:
pass
è completamente equivalente (a parte il loro nome :-) a questo:
class NewSpam(object):
pass
e a questo:
class Spam():
pass
Tutti hanno object
nel loro __bases__
.
>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]
In Python 2: eredita sempre in modo object
esplicito . Ottieni i vantaggi.
In Python 3: eredita da object
se stai scrivendo codice che cerca di essere agnostico in Python, cioè deve funzionare sia in Python 2 che in Python 3. Altrimenti, non fa davvero differenza, poiché Python lo inserisce per te dietro le quinte.
object
. IIRC ci fu un momento in cui non tutti i tipi incorporati venivano portati su classi di nuovo stile.
object
. Ho un Python 2.2.3 in giro e dopo un rapido controllo non sono riuscito a trovare un colpevole, ma riformulerò la risposta in seguito per renderlo più chiaro. Sarei interessato se potessi trovare un esempio, però, la mia curiosità è accesa.
object
nelle sue basi.
staticmethod
e classmethod
funziona perfettamente anche su lezioni di vecchio stile. property
sorta funziona per la lettura su classi di vecchio stile, non riesce a intercettare le scritture (quindi se si assegna al nome, l'istanza ottiene un attributo del nome dato che ombreggia la proprietà). Si noti inoltre che __slots__
il miglioramento della velocità di accesso agli attributi consiste principalmente nell'annullare la perdita che comporta l'accesso agli attributi di classe di nuovo stile, quindi non è realmente un punto di forza delle classi di nuovo stile (i risparmi di memoria sono comunque un punto di forza).
Python 3
class MyClass(object):
= Classe di nuovo stileclass MyClass:
= Classe new-style (eredita implicitamente da object
)Python 2
class MyClass(object):
= Classe di nuovo stileclass MyClass:
= CLASSE VECCHIO STILESpiegazione :
Quando si definiscono le classi di base in Python 3.x, è possibile eliminare la object
dalla definizione. Tuttavia, questo può aprire la porta a un problema seriamente difficile da rintracciare ...
Python ha introdotto classi di nuovo stile in Python 2.2, e ormai le classi di vecchio stile sono davvero piuttosto vecchie. La discussione sulle classi di vecchio stile è sepolta nei documenti 2.x e inesistente nei documenti 3.x.
Il problema è, la sintassi per le classi vecchio stile in Python 2.x è la stessa della sintassi alternativa per classi di nuovo stile in Python 3.x . Python 2.x è ancora molto usato (ad esempio GAE, Web2Py) e qualsiasi codice (o codificatore) che porta inconsapevolmente definizioni di classe in stile 3.x nel codice 2.x finirà con alcuni oggetti di base seriamente obsoleti. E poiché le lezioni di vecchio stile non sono sul radar di nessuno, probabilmente non sapranno cosa li ha colpiti.
Quindi basta spiegarlo a lungo e salvare alcune lacrime dagli sviluppatori 2.x.
__metaclass__ = type
in cima al modulo (dopo la from __future__ import absolute_import, division, print_function
riga :-)); è un hack di compatibilità in Py2 che rende tutte le classi successivamente definite nel modulo di nuovo stile di default, e in Py3, è completamente ignorato (solo una variabile globale casuale attorno), quindi è innocuo.
Sì, questo è un oggetto "nuovo stile". Era una funzionalità introdotta in python2.2.
Oggetti nuovi di stile hanno un modello diverso oggetto agli oggetti classici, e alcune cose non funzioneranno correttamente con oggetti in stile antico, per esempio, super()
, @property
e descrittori. Vedi questo articolo per una buona descrizione di cosa sia una nuova classe di stile.
Collegamento SO per una descrizione delle differenze: Qual è la differenza tra vecchio stile e nuove classi di stile in Python?
object
in Python 2.
Storia da Learn Python nel modo più duro :
La versione originale di Python di una classe è stata interrotta in molti modi seri. Quando fu riconosciuto che questo errore era già troppo tardi, e dovettero sostenerlo. Per risolvere il problema, avevano bisogno di uno stile di "nuova classe" in modo che le "vecchie classi" continuassero a funzionare ma è possibile utilizzare la nuova versione più corretta.
Decisero che avrebbero usato una parola "oggetto", in minuscolo, per essere la "classe" da cui erediti per creare una classe. È fonte di confusione, ma una classe eredita dalla classe denominata "oggetto" per creare una classe ma non è un oggetto in realtà è una classe, ma non dimenticare di ereditare dall'oggetto.
Inoltre, solo per farti sapere qual è la differenza tra le classi di nuovo stile e le classi di vecchio stile, è che le classi di nuovo stile ereditano sempre dalla object
classe o da un'altra classe ereditata da object
:
class NewStyle(object):
pass
Un altro esempio è:
class AnotherExampleOfNewStyle(NewStyle):
pass
Mentre una classe base vecchio stile assomiglia a questo:
class OldStyle():
pass
E una classe per bambini vecchio stile assomiglia a questo:
class OldStyleSubclass(OldStyle):
pass
Puoi vedere che una classe base Old Style non eredita da nessun'altra classe, tuttavia, le classi Old Style possono, ovviamente, ereditare l'una dall'altra. L'ereditarietà da oggetto garantisce che determinate funzionalità siano disponibili in ogni classe Python. Nuove classi di stile sono state introdotte in Python 2.2
object
non è poi così confuso, e in effetti è piuttosto standard. Smalltalk ha una classe radice denominata Object
e una metaclasse radice denominata Class
. Perché? Perché, così come Dog
è una classe per i cani, Object
è una classe per gli oggetti ed Class
è una classe per le classi. Java, C #, ObjC, Ruby e la maggior parte dei linguaggi OO basati su classi che le persone usano oggi che hanno una classe radice usano alcune varianti Object
come nome, non solo Python.
Sì, è storico . Senza di essa, crea una classe vecchio stile.
Se lo usi type()
su un oggetto vecchio stile, ottieni semplicemente "istanza". Su un oggetto di nuovo stile ottieni la sua classe.
type()
una classe vecchio stile, otterrai "classobj" invece di "tipo".
La sintassi dell'istruzione di creazione della classe:
class <ClassName>(superclass):
#code follows
In assenza di altre superclassi da cui si desidera ereditare in modo specifico, superclass
dovrebbe essere sempre object
, che è la radice di tutte le classi in Python.
object
è tecnicamente la radice delle classi "new-style" in Python. Ma le lezioni di nuovo stile oggi sono buone come essere l'unico stile di lezioni.
Ma, se non si usa esplicitamente la parola object
durante la creazione di classi, come altri hanno già detto, Python 3.x eredita implicitamente dalla object
superclasse. Ma credo che esplicito sia sempre meglio di implicito (inferno)