poo - La clase Python hereda el objeto.
poo python 3 (7)
¿Hay alguna razón para que una declaración de clase herede de un object
?
Acabo de encontrar un código que hace esto y no puedo encontrar una buena razón para ello.
class MyClass(object):
# class code follows...
¿Hay alguna razón para que una declaración de clase herede de un
object
?
tl; dr: En Python 3, aparte de la compatibilidad entre Python 2 y 3, no hay razón . En Python 2, muchas razones .
La historia de Python 2.x:
En Python 2.x (desde 2.2 en adelante) hay dos estilos de clases dependiendo de la presencia o ausencia de un object
como clase base:
Clases de estilo "clásico" : no tienen
object
como clase base:>>> class ClassicSpam: # no base class ... pass >>> ClassicSpam.__bases__ ()
"nuevas" clases de estilo : tienen, directa o indirectamente (por ejemplo, heredar de un tipo incorporado ),
object
como clase base:>>> class NewSpam(object): # directly inherit from object ... pass >>> NewSpam.__bases__ (<type ''object''>,) >>> class IntSpam(int): # indirectly inherit from object... ... pass >>> IntSpam.__bases__ (<type ''int''>,) >>> IntSpam.__bases__[0].__bases__ # ... because int inherits from object (<type ''object''>,)
Sin lugar a dudas, al escribir una clase siempre querrá ir a clases de nuevo estilo. Las ventajas de hacerlo son numerosas, para enumerar algunas de ellas:
Soporte para descriptores . Específicamente, las siguientes construcciones son posibles con descriptores:
-
classmethod
: método que recibe la clase como un argumento implícito en lugar de la instancia. -
staticmethod
: método que no recibe el argumento implícitoself
como primer argumento. - propiedades con
property
: crea funciones para gestionar la obtención, configuración y eliminación de un atributo. -
__slots__
: Guarda los consumos de memoria de una clase y también resulta en un acceso a atributos más rápido. Por supuesto, sí impone limitaciones .
-
El método estático
__new__
: le permite personalizar cómo se crean las nuevas instancias de clase.Orden de resolución de métodos (MRO) : en qué orden se buscarán las clases base de una clase al intentar resolver qué método llamar.
Relacionado con MRO,
super
llamadas . Ver también,super()
considerado super.
Si no hereda de object
, olvídese de estos. here puede encontrar una descripción más exhaustiva de los puntos de bala anteriores junto con otras ventajas de las "nuevas" clases de estilo.
Una de las desventajas de las clases de nuevo estilo es que la clase en sí misma requiere más memoria. Sin embargo, a menos que esté creando muchos objetos de clase, dudo que esto sea un problema y sea un hundimiento negativo en un mar de aspectos positivos.
Historia de Python 3.x:
En Python 3, las cosas están simplificadas. Solo existen clases de estilo nuevo (referidas simplemente como clases), por lo tanto, la única diferencia en la adición de object
requiere que escriba 8 caracteres más. Esta:
class ClassicSpam:
pass
Es completamente equivalente (aparte de su nombre :-) a esto:
class NewSpam(object):
pass
ya esto:
class Spam():
pass
todos tienen object
en sus __bases__
.
>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]
¿Entonces, qué debería hacer?
En Python 2: siempre se hereda de un object
explícitamente . Consigue los beneficios.
En Python 3: herede del object
si está escribiendo código que intenta ser agnóstico de Python, es decir, debe funcionar tanto en Python 2 como en Python 3. De lo contrario, no hay ninguna diferencia, ya que Python lo inserta. usted detrás de las escenas.
Esto crea una clase de nuevo estilo .
Historia de Learn Python the Hard Way :
La versión original de Python de una clase se rompió de muchas maneras serias. En el momento en que se reconoció este error, ya era demasiado tarde y tenían que soportarlo. Para solucionar el problema, necesitaban un estilo de "nueva clase" para que las "clases antiguas" siguieran funcionando, pero se puede usar la nueva versión más correcta.
Decidieron que usarían una palabra "objeto", en minúsculas, para ser la "clase" de la que se hereda para formar una clase. Es confuso, pero una clase hereda de la clase llamada "objeto" para crear una clase, pero no es un objeto en realidad es una clase, pero no olvide heredar de un objeto.
También para dejarte saber cuál es la diferencia entre las clases de estilo nuevo y las clases de estilo antiguo, es que las clases de estilo nuevo siempre heredan de la clase de object
o de otra clase que heredó del object
:
class NewStyle(object):
pass
Otro ejemplo es:
class AnotherExampleOfNewStyle(NewStyle):
pass
Mientras que una clase base de estilo antiguo se ve así:
class OldStyle():
pass
Y una clase de niños de estilo antiguo se ve así:
class OldStyleSubclass(OldStyle):
pass
Puede ver que una clase base de estilo antiguo no se hereda de ninguna otra clase, sin embargo, las clases de estilo antiguo pueden, por supuesto, heredarse unas de otras. La herencia del objeto garantiza que cierta funcionalidad esté disponible en cada clase de Python. Nuevas clases de estilo fueron introducidas en Python 2.2
La sintaxis de la declaración de creación de clase:
class <ClassName>(superclass):
#code follows
En ausencia de otras superclases de las que desea heredar específicamente, la superclass
siempre debe ser un object
, que es la raíz de todas las clases en Python.
object
es técnicamente la raíz de las clases de "nuevo estilo" en Python. Pero las clases de nuevo estilo de hoy son tan buenas como el único estilo de clases.
Pero, si no usa explícitamente la palabra object
al crear clases, entonces, como mencionan otros, Python 3.x hereda implícitamente de la superclase del object
. Pero supongo que explícito siempre es mejor que implícito (infierno)
Sí, es historical . Sin él, crea una clase de estilo antiguo.
Si usa type()
en un objeto de estilo antiguo, simplemente obtiene "instance". En un objeto de nuevo estilo obtienes su clase.
Sí, este es un objeto ''nuevo estilo''. Fue una característica introducida en python2.2.
Los objetos de estilo nuevo tienen un modelo de objeto diferente al de los objetos clásicos, y algunas cosas no funcionarán correctamente con objetos de estilo antiguo, por ejemplo, super()
, @property
y descriptores. Vea este artículo para una buena descripción de lo que es una nueva clase de estilo.
Enlace SO para una descripción de las diferencias: ¿Cuál es la diferencia entre el estilo antiguo y las clases de estilo nuevo en Python?
Python 3.x:
class MyClass(object):
= clase de nuevo estilo
class MyClass:
= clase de estilo nuevo (se hereda implícitamente del objeto)
Python 2.x:
class MyClass(object):
= clase de nuevo estilo
class MyClass:
= OLD-STYLE CLASS
Explicación:
Al definir clases base en Python 3.x, se le permite eliminar el objeto de la definición. Sin embargo, esto puede abrir la puerta para un problema realmente difícil de rastrear ...
Python introdujo clases de nuevo estilo en Python 2.2, y ahora las clases de estilo antiguo son bastante antiguas. La discusión de las clases de estilo antiguo está oculta en los documentos 2.x , y no existe en los documentos 3.x.
El problema es que la sintaxis para las clases de estilo antiguo en Python 2.x es la misma que la sintaxis alternativa para las clases de estilo nuevo en Python 3.x. Python 2.x todavía se usa mucho (por ejemplo, GAE, Web2Py), y cualquier código (o codificador) que, sin darse cuenta, incluya definiciones de clase de estilo 3.x en el código 2.x, va a terminar con algunos objetos base muy obsoletos. Y debido a que las clases de estilo antiguo no están en el radar de nadie, probablemente no sabrán qué les golpeó.
Así que simplemente explíquelo a lo largo y ahorre a los desarrolladores 2.x las lágrimas.