Quelle est la différence entre les classes de style ancien et nouveau en Python? Quand dois-je utiliser l'un ou l'autre?
Des classes New-style et classiques :
Jusqu'à Python 2.1, les classes à l'ancienne étaient la seule version disponible pour l'utilisateur.
Le concept de classe (à l'ancienne) n'est pas lié au concept de type: si
x
est une instance d'une classe à l'ancienne, ilx.__class__
désigne alors la classe dex
, mais l'type(x)
est toujours<type 'instance'>
.Cela reflète le fait que toutes les instances de style ancien, indépendamment de leur classe, sont implémentées avec un seul type intégré, appelé instance.
Des classes de nouveau style ont été introduites dans Python 2.2 pour unifier les concepts de classe et de type . Une classe de nouveau style est simplement un type défini par l'utilisateur, ni plus, ni moins.
Si x est une instance d'une classe de nouveau style, alors
type(x)
est généralement le même quex.__class__
(bien que cela ne soit pas garanti - une instance de classe de nouveau style est autorisée à remplacer la valeur renvoyée pourx.__class__
).La principale motivation pour introduire des classes de nouveau style est de fournir un modèle objet unifié avec un méta-modèle complet .
Il présente également un certain nombre d'avantages immédiats, comme la possibilité de sous-classer la plupart des types intégrés ou l'introduction de «descripteurs», qui permettent des propriétés calculées.
Pour des raisons de compatibilité, les classes sont toujours à l'ancienne par défaut .
Les classes de nouveau style sont créées en spécifiant une autre classe de nouveau style (c'est-à-dire un type) comme classe parente, ou l'objet "type de niveau supérieur" si aucun autre parent n'est nécessaire.
Le comportement des classes de style nouveau diffère de celui des classes de style ancien par un certain nombre de détails importants en plus du type renvoyé.
Certaines de ces modifications sont fondamentales pour le nouveau modèle d'objet, comme la façon dont les méthodes spéciales sont appelées. D'autres sont des "correctifs" qui ne pouvaient pas être implémentés auparavant pour des raisons de compatibilité, comme l'ordre de résolution des méthodes en cas d'héritage multiple.
Python 3 n'a que des classes de nouveau style .
Peu importe si vous sous-classe
object
ou non, les classes sont de nouveau style en Python 3.
type(x)
. Si je ne sous-classe pas un type intégré, il ne semble y avoir aucun avantage que je puisse voir des classes de nouveau style. Il y a un inconvénient, qui est le typage supplémentaire de(object)
.super()
ne fonctionnent pas sur les classes à l'ancienne. Sans oublier, comme le dit cet article, qu'il existe des correctifs fondamentaux, comme MRO, et des méthodes spéciales, ce qui est plus qu'une bonne raison de l'utiliser.Côté déclaration:
Les classes de nouveau style héritent de l' objet ou d'une autre classe de nouveau style.
Les classes à l'ancienne ne le font pas.
Python 3 Remarque:
Python 3 ne prend pas en charge les anciennes classes de style, donc l'une ou l'autre forme notée ci-dessus donne une classe de nouveau style.
la source
object
.class AnotherOldStyleClass: pass
class A: pass
etclass A(): pass
sont strictement équivalents. Le premier signifie "A n'hérite d'aucune classe parent" et le second signifie "A n'hérite d'aucune classe parent" . C'est assez similaire ànot is
etis not
Changements de comportement importants entre les anciennes et les nouvelles classes de style
Exception
(exemple ci-dessous)__slots__
ajoutéeMRO (Ordonnance de résolution de méthode) modifié
Il a été mentionné dans d'autres réponses, mais voici un exemple concret de la différence entre le MRO classique et le C3 MRO (utilisé dans les nouvelles classes de style).
La question est l'ordre dans lequel les attributs (qui incluent les méthodes et les variables membres) sont recherchés dans l'héritage multiple.
Les classes classiques effectuent une recherche approfondie de gauche à droite. Arrêtez-vous au premier match. Ils n'ont pas d'
__mro__
attribut.Les classes de nouveau style MRO sont plus compliquées à synthétiser en une seule phrase anglaise. Il est expliqué en détail ici . L'une de ses propriétés est qu'une classe de base n'est recherchée qu'une fois que toutes ses classes dérivées l'ont été. Ils ont l'
__mro__
attribut qui montre l'ordre de recherche.Les nouveaux objets de classe de style ne peuvent pas être levés sauf s'ils sont dérivés de
Exception
Autour de Python 2.5, de nombreuses classes pouvaient être augmentées, et autour de Python 2.6, cela a été supprimé. Sur Python 2.7.3:
la source
Les anciennes classes de style sont encore légèrement plus rapides pour la recherche d'attributs. Ce n'est généralement pas important, mais il peut être utile dans le code Python 2.x sensible aux performances:
la source
%timeit aobj.a
10000000 loops, best of 3: 66.1 ns per loop
%timeit bobj.a
10000000 loops, best of 3: 53.9 ns per loop
Guido a écrit The Inside Story on New-Style Classes , un très bon article sur les classes de style nouveau et ancien en Python.
Python 3 n'a qu'une nouvelle classe de style. Même si vous écrivez une «classe à l'ancienne», elle est implicitement dérivée de
object
.Les classes de nouveau style ont des fonctionnalités avancées qui font défaut aux classes de style ancien, telles que
super
la nouvelle C3 mro , certaines méthodes magiques, etc.la source
Voici une différence très pratique, vraie / fausse. La seule différence entre les deux versions du code suivant est que dans la deuxième version, Person hérite de object . En dehors de cela, les deux versions sont identiques, mais avec des résultats différents:
Cours à l'ancienne
Classes de nouveau style
la source
_names_cache
est un dictionnaire qui met en cache (stocke pour une récupération future) chaque nom que vous passezPerson.__new__
. La méthode setdefault (définie dans n'importe quel dictionnaire) prend deux arguments: une clé et une valeur. Si la clé est dans le dict, elle renverra sa valeur. Si ce n'est pas dans le dict, il le mettra d'abord à la valeur passée comme deuxième argument, puis le renverra.__new__()
est toujours appelé, et il construit toujours un nouvel objet, puis le lance. Dans ce cas, aif
est préférable à.setdefault()
.__new__
n'est pas vraiment une chose pour les classes à l'ancienne, il n'est pas utilisé dans la construction d'instance (c'est juste un nom aléatoire qui a l'air spécial, comme définir__spam__
). Ainsi, la construction de la classe à l'ancienne ne fait qu'appeler__init__
, tandis que la construction à nouveau style invoque__new__
(fusionnant à une instance singleton par son nom) pour la construire et l'__init__
initialiser.Les classes de nouveau style héritent de
object
et doivent être écrites comme telles dans Python 2.2 (c'est-class Classname(object):
à- dire au lieu declass Classname:
). Le principal changement consiste à unifier les types et les classes, et le bel effet secondaire de cela est qu'il vous permet d'hériter des types intégrés.Lisez descrintro pour plus de détails.
la source
Les nouvelles classes de style peuvent utiliser
super(Foo, self)
oùFoo
est une classe etself
est l'instance.Et dans Python 3.x, vous pouvez simplement utiliser à l'
super()
intérieur d'une classe sans aucun paramètre.la source