Pregunta

¿Cuál es la diferencia entre el estilo antiguo y el nuevo estilo de las clases en Python?Cuando debo usar uno o el otro?

¿Fue útil?

Solución

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

Hasta Python 2.1, de estilo antiguo, las clases eran el único sabor a disposición del usuario.

El concepto de (estilo antiguo) de la clase no está relacionado con el concepto de tipo:si x es una instancia de una clase de estilo, a continuación, x.__class__ designa a la clase de x, pero type(x) siempre es <type 'instance'>.

Esto refleja el hecho de que todo el estilo antiguo de los casos, independientemente de su clase, se llevan a cabo con un solo tipo integrado, llamado ejemplo.

Nuevo estilo de que se introdujeran las clases en Python 2.2 para unificar los conceptos de clase y tipo.Un nuevo estilo de clase es simplemente un tipo definido por el usuario, ni más, ni menos.

Si x es una instancia de una nueva clase de estilo, a continuación, type(x) es típicamente el mismo que x.__class__ (aunque esto no está garantizado – un nuevo estilo de la instancia de la clase está permitido reemplazar el valor devuelto para x.__class__).

La principal motivación para la introducción de nuevos estilo de clases es proporcionar un objeto único modelo con un total meta-modelo.

También tiene un número de ventajas inmediatas, como la capacidad para subclase de la mayoría de los tipos integrados, o la introducción de "descriptores", que permiten calculada propiedades.

Por razones de compatibilidad, las clases son aún de viejo estilo por defecto.

Nuevo estilo de las clases se crean mediante la especificación de un nuevo estilo de clase (es decir,un tipo) como una clase padre, o el "nivel superior" tipo de objeto si no otro de los padres es necesaria.

El comportamiento de las clases de estilo difiere de la de estilo antiguo las clases en una serie de detalles importantes, además de qué tipo devuelve.

Algunos de estos cambios son fundamentales en el nuevo modelo de objetos, como la forma especial de los métodos se invocan.Otros son "parches" que no podía de ser implementadas antes de los problemas de compatibilidad, como el método de la resolución de la orden en el caso de herencia múltiple.

Python 3 sólo tiene nuevo estilo de clases.

No importa si usted subclase de object o no, las clases de nuevo estilo en Python 3.

Otros consejos

La declaración de los sabios:

Nuevo estilo de las clases heredan de object, o de otro estilo nuevo de la clase.

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

Viejo las clases de estilo-no.

class OldStyleClass():
    pass

Importantes cambios de comportamiento entre el antiguo y el nuevo estilo de las clases

  • super agregó
  • MRO cambiado (se explica a continuación)
  • descriptores agregó
  • nuevo estilo de los objetos de la clase no puede ser elevado a menos que se derivan de Exception (ejemplo abajo)
  • __slots__ agregó

MRO (Método de Resolución de Orden) cambiado

Fue mencionado en otras respuestas, pero aquí va un ejemplo concreto de la diferencia entre el clásico MRO y C3 MRO (utilizado en el nuevo estilo de las clases).

La pregunta es el orden en el que los atributos (que incluyen métodos y variables miembro) se buscan en la herencia múltiple.

Clásico clases hacer una profundidad de búsqueda de la izquierda a la derecha.Parada en el primer partido.Ellos no tienen la __mro__ atributo.

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

Nuevo estilo de las clases MRO es más complicado sintetizar en una sola de las frases en inglés.Esto se explica en detalle aquí.Una de sus propiedades es que una clase Base es sólo buscó una vez que todas sus clases Derivadas han sido.Ellos tienen la __mro__ atributo que muestra el orden de búsqueda.

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)

Nuevo estilo de los objetos de la clase no puede ser elevado a menos que se derivan de Exception

Alrededor de Python 2.5 muchas clases podría ser elevado, alrededor de Python 2.6 esto fue eliminado.En 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

De estilo antiguo, las clases son todavía un poco más rápido para el atributo de búsqueda.Esto generalmente no es importante, pero puede ser útil en el rendimiento sensible a Python 2.x código:

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

Guido ha escrito La Historia de Nuevo las Clases de Estilo-, un gran artículo acerca de un estilo nuevo y el viejo estilo de la clase en Python.

Python 3 tiene sólo un estilo nuevo de la clase, incluso si usted escribe un 'viejo estilo de clase', implícitamente se derivan de object.

Nuevo estilo de las clases tienen algunas características avanzadas que carecen en el viejo estilo de las clases, tales como super y el nuevo C3 mro, algunos metodos magicos, etc.

He aquí una muy práctico, Verdadero/Falso diferencia.La única diferencia entre las dos versiones de el código siguiente es que en la segunda versión de la Persona que hereda de object.Aparte de que las dos versiones son idénticas, pero con resultados diferentes :

1) estilo antiguo clases

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) nuevo-estilo clases

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>
>>>

Nuevo estilo de las clases heredan object y debe ser escrita como tal en Python 2.2 en adelante (es decir, class Classname(object): en lugar de class Classname:).El núcleo del cambio es unificar los tipos y clases, y el efecto colateral de esto es que le permite heredar de tipos integrados.

Leer descrintro para obtener más detalles.

Nuevo estilo clases pueden utilizar super(Foo, self) donde Foo es una clase y self es la instancia.

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

Devolver un objeto proxy que los delegados de las llamadas de método para un padre o hermano de la clase de tipo.Esto es útil para tener acceso a los métodos heredados que han sido reemplaza en una clase.El orden de búsqueda es el mismo que el utilizado por getattr (), excepto que el tipo se omite.

Y en Python 3.x puede simplemente usar super() dentro de una clase sin parámetros.

O más bien, usted siempre debe usar el nuevo estilo de las clases, a menos que usted tiene el código que se necesita para trabajar con las versiones de Python mayores de 2.2.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top