Quelle est la différence entre les classes de style ancien et nouveau en Python?

Quelle est la différence entre les anciennes et les nouvelles classes de style en Python? Y a-t-il une raison d'utiliser des cours à l'ancienne de nos jours?

864
demandé sur laike9m 2008-09-10 22:01:27
la source

9 ответов

de http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes :

Jusqu'à Python 2.1, Les classes à l'ancienne étaient les seules saveurs disponibles pour l'utilisateur.

la notion de classe (ancienne) n'est pas liée à la notion de type: si x est une instance d'une classe de style ancien, alors x.__class__ désigne la classe de x , mais type(x) est toujours <type 'instance'> .

cela reflète le fait que toutes les instances de l'ancien style, indépendamment de leur classe, sont mis en œuvre avec un seul type, appelé instance.

les classes New-style ont été introduites en 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 typiquement le même que x.__class__ (bien que cela ne soit pas garanti – a nouvelle instance de classe de style est autorisée à annuler la valeur retournée pour x.__class__ ).

la principale motivation pour introduire des classes de nouveau style est de fournir un modèle d'objet unifié avec un méta-modèle complet .

Il a également un certain nombre d'avantages immédiats, comme la capacité de sous-classe de la plupart des types intégrés, ou l'introduction de "descripteurs", qui permettent les propriétés calculées.

pour des raisons de compatibilité, les classes sont encore à l'ancienne par défaut .

Les classes

New-style sont créées en spécifiant une autre classe new-style (i.e. un type) comme classe mère, ou l'objet "top-level type" si non autre parent est nécessaire.

le comportement des classes new-style diffère de celui de l'ancien style classes dans un certain nombre de détails importants en plus de quel type retourner.

Certains de ces changements sont fondamentaux pour le nouveau modèle objet, comme la façon dont les méthodes spéciales sont invoquées. D'autres sont des "correctifs" qui ne pourraient pas être mis en œuvre avant pour des problèmes de compatibilité, comme la méthode ordre de résolution en cas d'héritage multiple.

Python 3 n'a que des classes de nouveau style .

N'importe quelle matière si vous sous-classe de object ou non, les classes sont de nouveau style en Python 3.

493
répondu Projesh Bhoumik 2018-08-10 11:10:37
la source

déclaration-wise:

Nouveau style de classes héritent de l'objet, ou à partir d'un autre style nouveau de la classe.

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

les cours à L'ancienne ne le font pas.

class OldStyleClass():
    pass
283
répondu Mark Harrison 2011-12-21 02:12:38
la source

Importants changements de comportement entre l'ancien et le nouveau style de classes

  • super ajouté
  • MRO changé (expliqué ci-dessous)
  • descripteurs ajouté
  • les objets de la nouvelle classe de style ne peuvent être soulevés que s'ils sont dérivés de Exception (exemple ci-dessous)
  • __slots__ ajouté

MRO (Méthode de Résolution de l'Ordre) a changé

il a été mentionné dans d'autres réponses, mais voici un exemple concret de la différence entre MRO classique et C3 MRO (utilisé dans les nouvelles classes de style).

la question Est l'ordre dans lequel les attributs (qui comprennent les méthodes et les variables de membre) sont recherchés dans l'héritage multiple.

Classiques classes faites une première recherche en profondeur de gauche à droite. Arrêtez le premier match. Ils n'ont pas l'attribut __mro__ .

class C: i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 0
assert C21().i == 2

try:
    C12.__mro__
except AttributeError:
    pass
else:
    assert False

New-style classes MRO est plus compliqué à synthétiser dans une seule phrase en anglais. Il est expliqué en détail ici . 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 ont été. Ils ont l'attribut __mro__ qui montre ordre de recherche.

class C(object): i = 0
class C1(C): pass
class C2(C): i = 2
class C12(C1, C2): pass
class C21(C2, C1): pass

assert C12().i == 2
assert C21().i == 2

assert C12.__mro__ == (C12, C1, C2, C, object)
assert C21.__mro__ == (C21, C2, C1, C, object)

Nouveau style des objets de la classe ne peut être levé que si un dérivé de Exception

autour de python 2.5 beaucoup de classes pouvaient être soulevées, autour de python 2.6 cela a été supprimé. Sur Python 2.7.3:

# OK, old:
class Old: pass
try:
    raise Old()
except Old:
    pass
else:
    assert False

# TypeError, new not derived from `Exception`.
class New(object): pass
try:
    raise New()
except TypeError:
    pass
else:
    assert False

# OK, derived from `Exception`.
class New(Exception): pass
try:
    raise New()
except New:
    pass
else:
    assert False

# `'str'` is a new style object, so you can't raise it:
try:
    raise 'str'
except TypeError:
    pass
else:
    assert False
197
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 peut être utile dans Python 2 sensible aux performances.code x:

In [3]: class A:
   ...:     def __init__(self):
   ...:         self.a = 'hi there'
   ...: 

In [4]: class B(object):
   ...:     def __init__(self):
   ...:         self.a = 'hi there'
   ...: 

In [6]: aobj = A()
In [7]: bobj = B()

In [8]: %timeit aobj.a
10000000 loops, best of 3: 78.7 ns per loop

In [10]: %timeit bobj.a
10000000 loops, best of 3: 86.9 ns per loop
35
répondu xioxox 2010-07-12 15:26:52
la source

Guido a écrit the Inside Story on New-Style Classes , un très grand article sur le nouveau style et la classe de l'ancien style en Python.

Python 3 n'a que la classe new-style, même si vous écrivez une 'classe old-style', elle est implicitement dérivée de object .

New-style classes ont quelques caractéristiques avancées qui manquent dans les anciennes classes de style, comme super et le nouveau C3 mro , certains magiques méthodes, etc.

30
répondu Xiao Hanyu 2013-05-16 23:54:00
la source

Voici une différence très pratique, Vrai/Faux. La seule différence entre les deux versions du code suivant est que dans la deuxième version la personne hérite de l'objet. À part cela, les deux versions sont identiques, mais avec des résultats différents:

1) classes à l'ancienne

class Person():
    _names_cache = {}
    def __init__(self,name):
        self.name = name
    def __new__(cls,name):
        return cls._names_cache.setdefault(name,object.__new__(cls,name))

ahmed1 = Person("Ahmed")
ahmed2 = Person("Ahmed")
print ahmed1 is ahmed2
print ahmed1
print ahmed2


>>> False
<__main__.Person instance at 0xb74acf8c>
<__main__.Person instance at 0xb74ac6cc>
>>>

2) nouvelle-classes de style

class Person(object):
    _names_cache = {}
    def __init__(self,name):
        self.name = name
    def __new__(cls,name):
        return cls._names_cache.setdefault(name,object.__new__(cls,name))

ahmed1 = Person("Ahmed")
ahmed2 = Person("Ahmed")
print ahmed2 is ahmed1
print ahmed1
print ahmed2

>>> True
<__main__.Person object at 0xb74ac66c>
<__main__.Person object at 0xb74ac66c>
>>>
18
répondu ychaouche 2013-10-09 17:40:29
la source

les classes New-style héritent de object et doivent être écrites en Python à partir de la version 2.2 (i.e. class Classname(object): au lieu de class Classname: ). Le changement de base est d'unifier les types et les classes, et l'effet secondaire agréable de ceci est qu'il vous permet d'hériter des types intégrés.

Lire descrintro pour plus de détails.

7
répondu Halo 2013-03-20 19:09:52
la source

Nouvelles classes de style peut utiliser des super(Foo, self)Foo est une classe et self est l'exemple.

super(type[, object-or-type])

renvoie un objet de procuration qui délègue les appels de méthode à une classe de type de parent ou de frère ou sœur. Ceci est utile pour accéder aux méthodes héritées qui ont été dépassées dans une classe. L'ordre de recherche est le même que celui utilisé par getattr (), sauf que le type lui-même est ignorée.

et en Python 3.x vous pouvez simplement utiliser super() dans une classe sans paramètres.

4
répondu jamylak 2013-04-30 12:28:52
la source

ou plutôt, vous devriez toujours utiliser des classes de nouveau style, sauf si vous avez du code qui doit fonctionner avec des versions de Python plus anciennes que 2.2.

3
répondu Tony Meyer 2008-09-11 01:23:53
la source

Autres questions sur python types class oop new-style-class