La réponse à cette question (bien que simple) est assez difficile à trouver. Googler des choses comme "classe de base d'objets python" ou similaire propose des pages et des pages de tutoriels sur la programmation orientée objet. Voter parce que c'est le premier lien qui m'a conduit aux termes de recherche "objets python anciens vs nouveaux styles"
vastlysuperiorman
Réponses:
765
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 .
Histoire de Python 2.x:
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 objectclasse de base:
classes de style "classique" : elles n'ont pas objectcomme classe de base:
>>>classClassicSpam:# no base class...pass>>>ClassicSpam.__bases__
()
"nouvelles" classes de style : elles ont, directement ou indirectement (par exemple hériter d'un type intégré ), objectcomme classe de base:
>>>classNewSpam(object):# directly inherit from object...pass>>>NewSpam.__bases__
(<type 'object'>,)>>>classIntSpam(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:
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.
propriétés avec 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.
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.
Histoire de Python 3.x:
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 objectest de vous obliger à taper 8 caractères supplémentaires. Cette:
classClassicSpam:pass
est complètement équivalent (à part leur nom :-) à ceci:
classNewSpam(object):pass
et à cela:
classSpam():pass
Tous ont objecten leur __bases__.
>>>[object in cls.__bases__ for cls in{Spam,NewSpam,ClassicSpam}][True,True,True]
Alors, que devrais-tu faire?
En Python 2: toujours hérité de objectexplicitement . Obtenez les avantages.
En Python 3: héritez de objectsi 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.
"selon la présence ou l'absence d'un type intégré en tant que classe de base" => en réalité, il ne s'agit pas "d'absence ou de présence d'un type intégré en tant que classe de base", mais si la classe hérite - directement ou indirectement - de 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.
bruno desthuilliers
@brunodesthuilliers Mon impression était que tous les types intégrés héritaient de 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.
Dimitris Fasarakis Hilliard
En toute honnêteté (cf. "IIRC" dans mon commentaire précédent), je ne suis pas sûr à 101% de ce point (si tous les types intégrés ont déjà été convertis en classes de nouveau style lorsque les classes de nouveau style ont été introduites) - je pourrais être simple mal, ou cela pourrait ne concerner que certains types de lib standard (mais pas intégré). Mais pourtant, je pense qu'il devrait être préférable de clarifier ce qui fait qu'une classe de nouveau style objecta ses bases.
bruno desthuilliers
7
trop mauvais stackoverflow ne fait que upvote = upvote + 1 pour ces réponses un peu, j'aimerais pouvoir faire upvote + = N
PirateApp
1
staticmethodet classmethodfonctionne très bien même sur les classes à l'ancienne. propertysorta 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).
ShadowRanger
540
Python 3
class MyClass(object): = Classe de nouveau style
class MyClass:= Classe de nouveau style (hérite implicitement de object)
Python 2
class MyClass(object): = Classe de nouveau style
class MyClass:= CLASSE ANCIENNE
Explication :
Lors de la définition des classes de base dans Python 3.x, vous êtes autorisé à supprimer la objectde 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.
"Lors de la définition des classes de base dans Python 3.x, vous êtes autorisé à supprimer l'objet de la définition. Cependant, cela peut ouvrir la porte à un problème très difficile à suivre ..." À quels problèmes faites-vous référence?
Aidis
6
@Aidis: Je pense qu'ils signifient que le code qui s'exécute à la fois sur Py2 et Py3 conviendrait à Py3, mais serait rompu à Py2 s'il s'appuie sur des fonctionnalités de classe de nouveau style. Personnellement, si j'écris du code comme ça, j'omet l'héritage explicite et je le mets juste __metaclass__ = typeen haut du module (après la from __future__ import absolute_import, division, print_functionligne :-)); 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.
ShadowRanger
400
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(), @propertyet les descripteurs. Consultez cet article pour une bonne description de ce qu'est une nouvelle classe de style.
+1 Ceci. Notez que les classes à l'ancienne ont disparu en Python 3, vous n'avez donc qu'à hériter de objectPython 2.
9
Ce n'est pas une vraie réponse. ı fait simplement référence à d'autres articles. Je pense que la réponse de Yarin devrait être acceptée comme réponse à cette question.
alwbtc
2
@alwbtc: Cette réponse a aussi quelque chose de nouveau. Par exemple, la mention de "super ()" m'a conduit à un autre important [ici] ( stackoverflow.com/questions/576169/… ).
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 objectclasse ou d'une autre classe qui a hérité de object:
classNewStyle(object):pass
Un autre exemple est:
classAnotherExampleOfNewStyle(NewStyle):pass
Alors qu'une classe de base à l'ancienne ressemble à ceci:
classOldStyle():pass
Et une classe enfant à l'ancienne ressemble à ceci:
classOldStyleSubclass(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
Appeler la classe racine objectn'est pas si déroutant, et en fait c'est assez standard. Smalltalk a une classe racine nommée Objectet une métaclasse racine nommée Class. Pourquoi? Parce que, tout comme Dogune classe pour chiens, Objectest une classe pour objets et Classest 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 Objectcomme nom, pas seulement Python.
abarnert
30
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.
De plus, si vous utilisez type()une classe à l'ancienne, vous obtenez "classobj" au lieu de "type".
Joel Sjögren
7
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 superclassdevrait toujours être object, qui est la racine de toutes les classes en Python.
objectest 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 objectlors de la création de classes, alors comme d'autres l'ont mentionné, Python 3.x hérite implicitement de la objectsuperclasse. Mais je suppose qu'explicite vaut toujours mieux qu'implicite (enfer)
Réponses:
En Python 3, mis à part la compatibilité entre Python 2 et 3, aucune raison . En Python 2, plusieurs raisons .
Histoire de Python 2.x:
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:"nouvelles" classes de style : elles ont, directement ou indirectement (par exemple hériter d'un type intégré ),
object
comme classe de base: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 impliciteself
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.
Histoire de Python 3.x:
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:est complètement équivalent (à part leur nom :-) à ceci:
et à cela:
Tous ont
object
en leur__bases__
.Alors, que devrais-tu faire?
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.la source
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
etclassmethod
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 deobject
)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.
la source
__metaclass__ = type
en haut du module (après lafrom __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?
la source
object
Python 2.L'histoire de Learn Python the Hard Way :
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é deobject
:Un autre exemple est:
Alors qu'une classe de base à l'ancienne ressemble à ceci:
Et une classe enfant à l'ancienne ressemble à ceci:
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
la source
object
n'est pas si déroutant, et en fait c'est assez standard. Smalltalk a une classe racine nomméeObject
et une métaclasse racine nomméeClass
. Pourquoi? Parce que, tout commeDog
une classe pour chiens,Object
est une classe pour objets etClass
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 deObject
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.la source
type()
une classe à l'ancienne, vous obtenez "classobj" au lieu de "type".La syntaxe de l'instruction de création de classe:
En l'absence d'autres superclasses dont vous souhaitez spécifiquement hériter, la
superclass
devrait toujours êtreobject
, 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 laobject
superclasse. Mais je suppose qu'explicite vaut toujours mieux qu'implicite (enfer)Référence
la source