¿Hay alguna razón para que una declaración de clase herede object
?
Acabo de encontrar un código que hace esto y no puedo encontrar una buena razón.
class MyClass(object):
# class code follows...
¿Hay alguna razón para que una declaración de clase herede object
?
Acabo de encontrar un código que hace esto y no puedo encontrar una buena razón.
class MyClass(object):
# class code follows...
Respuestas:
¿Hay alguna razón para que una declaración de clase herede
object
?
En Python 3, aparte de la compatibilidad entre Python 2 y 3, no hay razón . En Python 2, muchas razones .
En Python 2.x (desde 2.2 en adelante) hay dos estilos de clases dependiendo de la presencia o ausencia de object
una clase base:
Clases de estilo "clásico" : no tienen object
como clase base:
>>> class ClassicSpam: # no base class
... pass
>>> ClassicSpam.__bases__
()
Clases de estilo "nuevas" : tienen, directa o indirectamente (por ejemplo, heredar de un tipo incorporado ), object
como una 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 duda, al escribir una clase siempre querrás ir a clases de estilo nuevo. Las ventajas de hacerlo son numerosas, para enumerar algunas de ellas:
Soporte para descriptores . Específicamente, las siguientes construcciones son posibles con descriptores:
classmethod
: Un método que recibe la clase como un argumento implícito en lugar de la instancia.staticmethod
: Un método que no recibe el argumento implícito self
como primer argumento.property
: Crear 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 da como resultado un acceso de atributos más rápido. Por supuesto, impone limitaciones .El __new__
método estático: le permite personalizar cómo se crean nuevas instancias de clase.
Orden de resolución de método (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 heredas de object
, olvídate de estos. Aquí se puede encontrar una descripción más exhaustiva de los puntos anteriores junto con otras ventajas de las "nuevas" clases de estilo .
Una de las desventajas de las clases de estilo nuevo 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 que sea un hundimiento negativo en un mar de positivos.
En Python 3, las cosas se simplifican. Solo existen clases de estilo nuevo (a las que se hace referencia claramente como clases), por lo que la única diferencia al agregar object
es que debe escribir 8 caracteres más. Esta:
class ClassicSpam:
pass
es completamente equivalente (aparte de su nombre :-) a esto:
class NewSpam(object):
pass
y a esto:
class Spam():
pass
Todos tienen object
en su __bases__
.
>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]
En Python 2: siempre herede de forma object
explícita . Obtén las ventajas.
En Python 3: herede object
si está escribiendo código que intenta ser independiente de Python, es decir, debe funcionar tanto en Python 2 como en Python 3. De lo contrario, no hay diferencia, ya que Python lo inserta por usted entre bastidores.
object
. IIRC hubo un punto en el tiempo en el que no todos los tipos incorporados fueron transferidos a clases de estilo nuevo todavía.
object
. Tengo un Python 2.2.3 alrededor y, después de una comprobación rápida, no pude encontrar un delincuente, pero volveré a redactar la respuesta más adelante para aclararlo. Sin embargo, me interesaría si pudieras encontrar un ejemplo, mi curiosidad se despertó.
object
en sus bases.
staticmethod
y classmethod
funciona bien incluso en clases de estilo antiguo. property
más o menos funciona para leer en clases de estilo antiguo, simplemente no intercepta las escrituras (por lo tanto, si asigna el nombre, la instancia obtiene un atributo del nombre dado que sombrea la propiedad). También tenga en cuenta que __slots__
la mejora en la velocidad de acceso al atributo se trata principalmente de deshacer la pérdida en la que incurre el acceso al atributo de la clase de estilo nuevo, por lo que no es realmente un punto de venta de las clases de estilo nuevo (aunque el ahorro de memoria es un punto de venta).
Python 3
class MyClass(object):
= Clase de nuevo estiloclass MyClass:
= Clase de estilo nuevo (hereda implícitamente de object
)Python 2
class MyClass(object):
= Clase de nuevo estiloclass MyClass:
= CLASE DE ESTILO ANTIGUOExplicacion :
Al definir clases base en Python 3.x, se le permite soltar el object
de la definición. Sin embargo, esto puede abrir la puerta a un problema realmente difícil de rastrear ...
Python introdujo clases de estilo nuevo en Python 2.2, y ahora las clases de estilo antiguo son realmente bastante antiguas. La discusión de las clases de estilo antiguo está enterrada 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 ampliamente (por ejemplo, GAE, Web2Py), y cualquier código (o codificador) que, sin saberlo, traiga definiciones de clase de estilo 3.x al código 2.x terminará con algunos objetos base muy desactualizados. 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 deletrearlo en el camino largo y salvar a algunos desarrolladores 2.x las lágrimas.
__metaclass__ = type
en la parte superior del módulo (después de la from __future__ import absolute_import, division, print_function
línea :-)); es un truco de compatibilidad en Py2 que hace que todas las clases definidas posteriormente en el módulo sean de nuevo estilo por defecto, y en Py3, se ignora por completo (solo una variable global aleatoria sentada), por lo que es inofensivo.
Sí, este es un objeto 'nuevo estilo'. Era una característica introducida en python2.2.
Los nuevos objetos de estilo tienen un modelo de objeto diferente a los objetos clásicos, y algunas cosas no funcionarán correctamente con objetos de estilo antiguos, por ejemplo super()
, @property
y descriptores. Consulte este artículo para obtener 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 nuevas clases de estilo en Python?
object
en Python 2.
Historia de Learn Python the Hard Way :
La versión original de Python de una clase se rompió de muchas maneras serias. Cuando se reconoció esta falla, ya era demasiado tarde y tuvieron que apoyarla. Para solucionar el problema, necesitaban un estilo de "nueva clase" para que las "viejas clases" siguieran funcionando, pero puede usar la nueva versión más correcta.
Decidieron que usarían una palabra "objeto", en minúscula, para ser la "clase" de la que se hereda para hacer una clase. Es confuso, pero una clase hereda de la clase llamada "objeto" para hacer una clase, pero no es un objeto realmente es una clase, pero no olvide heredar del objeto.
También para hacerle 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 object
clase o de otra clase que hereda de 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 infantil de estilo antiguo se ve así:
class OldStyleSubclass(OldStyle):
pass
Puede ver que una clase base de Old Style no hereda de ninguna otra clase, sin embargo, las clases de Old Style pueden, por supuesto, heredarse entre sí. La herencia del objeto garantiza que cierta funcionalidad esté disponible en cada clase de Python. Se introdujeron nuevas clases de estilo en Python 2.2
object
no es tan confuso, y de hecho es bastante estándar. Smalltalk tiene una clase raíz llamada Object
y una metaclase raíz llamada Class
. ¿Por qué? Porque, tal como Dog
es una clase para perros, Object
es una clase para objetos, y Class
es una clase para clases. Java, C #, ObjC, Ruby y la mayoría de los otros lenguajes OO basados en clases que las personas usan hoy en día que tienen una clase raíz usan alguna variación Object
como nombre, no solo Python.
Sí, es histórica . Sin ella, crea una clase de estilo antiguo.
Si usa type()
un objeto de estilo antiguo, solo obtiene "instancia". En un objeto de nuevo estilo obtienes su clase.
type()
en una clase de estilo antiguo, obtiene "classobj" en lugar de "tipo".
La sintaxis de la declaración de creación de clase:
class <ClassName>(superclass):
#code follows
En ausencia de cualquier otra superclase de la que desee heredar específicamente, superclass
siempre debería ser 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 estilo nuevo de hoy son tan buenas como ser el único estilo de clases.
Pero, si no usa explícitamente la palabra object
al crear clases, entonces, como otros mencionaron, Python 3.x hereda implícitamente de la object
superclase. Pero supongo que explícito siempre es mejor que implícito (infierno)