Y a-t-il une raison pour qu'une déclaration de classe hérite object
?
Je viens de trouver du code qui fait cela et je ne trouve pas de bonne raison.
class MyClass(object):
# class code follows...
Y a-t-il une raison pour qu'une déclaration de classe hérite object
?
Je viens de trouver du code qui fait cela et je ne trouve pas de bonne raison.
class MyClass(object):
# class code follows...
Réponses:
Y a-t-il une raison pour qu'une déclaration de classe hérite
object
?
En Python 3, mis à part la compatibilité entre Python 2 et 3, aucune raison . En Python 2, plusieurs raisons .
Dans Python 2.x (à partir de la version 2.2), il existe deux styles de classes en fonction de la présence ou de l'absence de object
classe de base:
classes de style "classique" : elles n'ont pas object
comme classe de base:
>>> class ClassicSpam: # no base class
... pass
>>> ClassicSpam.__bases__
()
"nouvelles" classes de style : elles ont, directement ou indirectement (par exemple hériter d'un type intégré ), object
comme classe de 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'>,)
Sans aucun doute, lors de l'écriture d'une classe, vous aurez toujours envie d'opter pour des classes de nouveau style. Les avantages de le faire sont nombreux, pour en énumérer certains:
Prise en charge des descripteurs . Plus précisément, les constructions suivantes sont rendues possibles avec des descripteurs:
classmethod
: Une méthode qui reçoit la classe comme argument implicite au lieu de l'instance.staticmethod
: Une méthode qui ne reçoit pas l'argument implicite self
comme premier argument.property
: Créer des fonctions pour gérer l'obtention, la définition et la suppression d'un attribut.__slots__
: Enregistre les consommations de mémoire d'une classe et accélère également l'accès aux attributs. Bien sûr, cela impose des limitations .La __new__
méthode statique: vous permet de personnaliser la façon dont les nouvelles instances de classe sont créées.
Ordre de résolution des méthodes (MRO) : dans quel ordre les classes de base d'une classe seront recherchées lors de la tentative de résolution de la méthode à appeler.
Lié au MRO, aux super
appels . Voir aussi, super()
considéré comme super.
Si vous n'héritez pas object
, oubliez-les. Une description plus exhaustive des puces précédentes ainsi que d'autres avantages des "nouvelles" classes de style peuvent être trouvées ici .
L'un des inconvénients des classes de nouveau style est que la classe elle-même est plus gourmande en mémoire. À moins que vous ne créiez de nombreux objets de classe, je doute que ce soit un problème et que ce soit un naufrage négatif dans une mer de points positifs.
En Python 3, les choses sont simplifiées. Seules les classes de nouveau style existent (appelées clairement classes) donc la seule différence dans l'ajout object
est de vous obliger à taper 8 caractères supplémentaires. Cette:
class ClassicSpam:
pass
est complètement équivalent (à part leur nom :-) à ceci:
class NewSpam(object):
pass
et à cela:
class Spam():
pass
Tous ont object
en leur __bases__
.
>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]
En Python 2: toujours hérité de object
explicitement . Obtenez les avantages.
En Python 3: héritez de object
si vous écrivez du code qui essaie d'être agnostique Python, c'est-à-dire qu'il doit fonctionner à la fois en Python 2 et en Python 3. Sinon, cela ne fait vraiment aucune différence puisque Python l'insère pour vous Dans les coulisses.
object
. IIRC il y a eu un moment où tous les types intégrés n'étaient pas encore portés vers des classes de nouveau style.
object
. J'ai un Python 2.2.3 autour et après une vérification rapide, je n'ai pas trouvé de délinquant, mais je reformulerai la réponse plus tard pour que ce soit plus clair. Serait intéressé si vous pouviez trouver un exemple, ma curiosité est piquée.
object
a ses bases.
staticmethod
et classmethod
fonctionne très bien même sur les classes à l'ancienne. property
sorta fonctionne pour la lecture sur les classes à l'ancienne, il échoue tout simplement à intercepter les écritures (donc si vous attribuez au nom, l'instance gagne un attribut du nom donné qui masque la propriété). Notez également que __slots__
l'amélioration de la vitesse d'accès aux attributs consiste principalement à annuler la perte subie par l'accès aux attributs de classe de nouveau style, donc ce n'est pas vraiment un argument de vente des classes de nouveau style (les économies de mémoire sont un argument de vente cependant).
Python 3
class MyClass(object):
= Classe de nouveau styleclass MyClass:
= Classe de nouveau style (hérite implicitement de object
)Python 2
class MyClass(object):
= Classe de nouveau styleclass MyClass:
= CLASSE ANCIENNEExplication :
Lors de la définition des classes de base dans Python 3.x, vous êtes autorisé à supprimer la object
de la définition. Cependant, cela peut ouvrir la porte à un problème très difficile à suivre…
Python a réintroduit des classes de nouveau style dans Python 2.2, et maintenant les classes de style ancien sont vraiment assez anciennes. La discussion sur les classes à l'ancienne est enterrée dans les documents 2.x et inexistante dans les documents 3.x.
Le problème est, la syntaxe pour les classes de style ancien en Python 2.x est la même que la syntaxe alternative pour les classes de nouveau style 3.x Python . Python 2.x est encore très largement utilisé (par exemple GAE, Web2Py), et tout code (ou codeur) apportant involontairement des définitions de classe de style 3.x dans le code 2.x va se retrouver avec des objets de base sérieusement obsolètes. Et parce que les cours à l'ancienne ne sont sur le radar de personne, ils ne sauront probablement pas ce qui les a frappés.
Il suffit donc de l'épeler sur le long chemin et de sauver un développeur 2.x les larmes.
__metaclass__ = type
en haut du module (après la from __future__ import absolute_import, division, print_function
ligne :-)); c'est un piratage de compatibilité dans Py2 qui rend toutes les classes définies par la suite dans le module nouveau style par défaut, et dans Py3, il est complètement ignoré (juste une variable globale aléatoire assise), donc c'est inoffensif.
Oui, c'est un objet "nouveau style". C'était une fonctionnalité introduite dans python2.2.
Les nouveaux objets de style ont un modèle d'objet différent des objets classiques, et certaines choses ne fonctionneront pas correctement avec les objets de style ancien, par exemple super()
, @property
et les descripteurs. Consultez cet article pour une bonne description de ce qu'est une nouvelle classe de style.
Lien SO pour une description des différences: Quelle est la différence entre les classes de style ancien et nouveau en Python?
object
Python 2.
L'histoire de Learn Python the Hard Way :
L'interprétation originale d'une classe par Python a été interrompue de nombreuses manières graves. Au moment où cette faute a été reconnue, il était déjà trop tard et ils ont dû la soutenir. Afin de résoudre le problème, ils avaient besoin d'un style de "nouvelle classe" pour que les "anciennes classes" continuent de fonctionner mais vous pouvez utiliser la nouvelle version plus correcte.
Ils ont décidé qu'ils utiliseraient un mot "objet", en minuscule, pour être la "classe" dont vous héritez pour créer une classe. C'est déroutant, mais une classe hérite de la classe nommée "objet" pour en faire une classe mais ce n'est pas vraiment un objet c'est une classe, mais n'oubliez pas d'hériter de l'objet.
Aussi pour vous faire savoir quelle est la différence entre les classes de nouveau style et les classes de style ancien, c'est que les classes de nouveau style héritent toujours de la object
classe ou d'une autre classe qui a hérité de object
:
class NewStyle(object):
pass
Un autre exemple est:
class AnotherExampleOfNewStyle(NewStyle):
pass
Alors qu'une classe de base à l'ancienne ressemble à ceci:
class OldStyle():
pass
Et une classe enfant à l'ancienne ressemble à ceci:
class OldStyleSubclass(OldStyle):
pass
Vous pouvez voir qu'une classe de base Old Style n'hérite d'aucune autre classe, cependant, les classes Old Style peuvent, bien sûr, hériter les unes des autres. L'héritage de l'objet garantit que certaines fonctionnalités sont disponibles dans chaque classe Python. De nouvelles classes de style ont été introduites dans Python 2.2
object
n'est pas si déroutant, et en fait c'est assez standard. Smalltalk a une classe racine nommée Object
et une métaclasse racine nommée Class
. Pourquoi? Parce que, tout comme Dog
une classe pour chiens, Object
est une classe pour objets et Class
est une classe pour classes. Java, C #, ObjC, Ruby et la plupart des autres langages OO basés sur les classes que les gens utilisent aujourd'hui et qui ont une classe racine utilisent une certaine variation de Object
comme nom, pas seulement Python.
Oui, c'est historique . Sans cela, il crée une classe à l'ancienne.
Si vous utilisez type()
sur un objet à l'ancienne, vous obtenez simplement "instance". Sur un objet de nouveau style, vous obtenez sa classe.
type()
une classe à l'ancienne, vous obtenez "classobj" au lieu de "type".
La syntaxe de l'instruction de création de classe:
class <ClassName>(superclass):
#code follows
En l'absence d'autres superclasses dont vous souhaitez spécifiquement hériter, la superclass
devrait toujours être object
, qui est la racine de toutes les classes en Python.
object
est techniquement la racine des classes "new-style" en Python. Mais les classes de nouveau style aujourd'hui sont aussi bonnes que d'être le seul style de classes.
Mais, si vous n'utilisez pas explicitement le mot object
lors de la création de classes, alors comme d'autres l'ont mentionné, Python 3.x hérite implicitement de la object
superclasse. Mais je suppose qu'explicite vaut toujours mieux qu'implicite (enfer)