Solución:
De Clases clásicas y de estilo nuevo:
Hasta Python 2.1, las clases de estilo antiguo eran el único sabor disponible para el usuario.
El concepto de clase (de estilo antiguo) no está relacionado con el concepto de tipo: si
x
es una instancia de una clase de estilo antiguo, entoncesx.__class__
designa la clase dex
, perotype(x)
es siempre<type
.
'instance'>Esto refleja el hecho de que todas las instancias de estilo antiguo, independientemente de su clase, se implementan con un solo tipo incorporado, llamado instancia.
Se introdujeron clases de nuevo estilo en Python 2.2 para unificar los conceptos de clase y tipo. Una clase de estilo nuevo es simplemente un tipo definido por el usuario, ni más ni menos.
Si x es una instancia de una clase de estilo nuevo, entonces
type(x)
es típicamente lo mismo quex.__class__
(aunque esto no está garantizado, se permite que una instancia de clase de estilo nuevo anule el valor devuelto parax.__class__
).La principal motivación para introducir clases de nuevo estilo es proporcionar un modelo de objetos unificado con un metamodelo completo..
También tiene una serie de beneficios inmediatos, como la capacidad de crear subclases de la mayoría de los tipos integrados o la introducción de “descriptores”, que habilitan propiedades calculadas.
Por razones de compatibilidad, las clases siguen siendo antiguas de forma predeterminada..
Las clases de estilo nuevo se crean especificando otra clase de estilo nuevo (es decir, un tipo) como clase principal, o el objeto “tipo de nivel superior” si no se necesita ningún otro padre.
El comportamiento de las clases de estilo nuevo difiere del de las clases de estilo antiguo en una serie de detalles importantes además del tipo que devuelve.
Algunos de estos cambios son fundamentales para el nuevo modelo de objetos, como la forma en que se invocan los métodos especiales. Otros son “arreglos” que no se podían implementar antes por cuestiones de compatibilidad, como el orden de resolución del método en caso de herencia múltiple.
Python 3 solo tiene clases de estilo nuevo.
No importa si eres una subclase de
object
o no, las clases son de nuevo estilo en Python 3.
Declaración-sabio:
Las clases de nuevo estilo heredan de objeto, o de otra clase de estilo nuevo.
class NewStyleClass(object):
pass
class AnotherNewStyleClass(NewStyleClass):
pass
Las clases de estilo antiguo no lo hacen.
class OldStyleClass():
pass
Nota de Python 3:
Python 3 no admite clases de estilo antiguo, por lo que cualquiera de las formas mencionadas anteriormente da como resultado una clase de estilo nuevo.
Cambios importantes de comportamiento entre clases de estilo antiguas y nuevas
- super añadido
- MRO cambiado (explicado a continuación)
- descriptores agregados
- Los nuevos objetos de clase de estilo no se pueden generar a menos que se deriven de
Exception
(ejemplo a continuación) -
__slots__
adicional
MRO (orden de resolución de método) ha cambiado
Se mencionó en otras respuestas, pero aquí va un ejemplo concreto de la diferencia entre el MRO clásico y el MRO C3 (utilizado en las nuevas clases de estilo).
La pregunta es el orden en el que se buscan los atributos (que incluyen métodos y variables miembro) en la herencia múltiple.
Clases clásicas Realice una búsqueda en profundidad de izquierda a derecha. Detente en el primer partido. No tienen el __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
Clases de nuevo estilo MRO es más complicado de sintetizar en una sola oración en inglés. Se explica en detalle aquí. Una de sus propiedades es que una clase base solo se busca una vez que se han realizado todas sus clases derivadas. Ellos tienen el __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)
Los nuevos objetos de clase de estilo no se pueden generar a menos que se deriven de Exception
Alrededor de Python 2.5 se pudieron generar muchas clases, y alrededor de Python 2.6 se eliminó. 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