¿Por qué las clases de Python heredan el objeto?

¿Hay alguna razón para heredar una declaración de clase? object?

Acabo de encontrar un código que hace esto y no puedo encontrar una buena razón.

class MyClass(object):
    # class code follows...

preguntado Oct 25 '10, 11:10

Esto crea un clase de nuevo estilo. -

La respuesta a esta pregunta (aunque simple) es bastante difícil de encontrar. Al buscar en Google cosas como "clase base de objetos de Python" o similares, aparecen páginas y páginas de tutoriales sobre programación orientada a objetos. Voto a favor porque este es el primer enlace que me llevó a los términos de búsqueda "objetos de Python de estilo antiguo frente a nuevo" -

Para la parte "cómo buscar esta pregunta", SímboloHound es una opción. -

6 Respuestas

¿Hay alguna razón para heredar una declaración de clase? object?

En Python 3, además de la compatibilidad entre Python 2 y 3, Sin razón. En Python 2, muchas razones.


Historia de Python 2.x:

En Python 2.x (de 2.2 en adelante) hay dos estilos de clases dependiendo de la presencia o ausencia de object como clase base:

  1. "estilo clásico clases: no tienen object como clase base:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
    
  2. "nuevo estilo clases: tienen, directamente 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 duda, al escribir una clase siempre quiero 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:

    1. classmethod: Un método que recibe la clase como un argumento implícito en lugar de la instancia.
    2. staticmethod: Un método que no recibe el argumento implícito self como primer argumento.
    3. propiedades con property: Crea funciones para gestionar la obtención, configuración y eliminación de un atributo.
    4. __slots__: Guarda el consumo de memoria de una clase y también da como resultado un acceso a atributos más rápido. Claro que lo hace imponer limitaciones.
  • La __new__ método estático: le permite personalizar cómo se crean las nuevas instancias de clase.

  • Orden de resolución del 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. Vea también, super() considerado super.

Si no heredas de object, olvídate de estos. Se puede encontrar una descripción más exhaustiva de los puntos anteriores junto con otras ventajas de las clases de estilo "nuevas". aquí.

Una de las desventajas de las clases de estilo nuevo es que la clase en sí requiere más memoria. Sin embargo, a menos que esté creando muchos objetos de clase, dudo que esto sea un problema y es un hundimiento negativo en un mar de aspectos positivos.


Historia de Python 3.x:

En Python 3, las cosas se simplifican. Solo existen clases de estilo nuevo (denominadas simplemente clases), por lo que la única diferencia en agregar object requiere que escriba 8 caracteres más. Esto:

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]

Entonces, ¿qué debe hacer?

En Python 2: heredar siempre de object explícitamente. Obtenga las ventajas.

En Python 3: heredar de 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 lo haga, realmente no hay diferencia, ya que Python lo inserta detrás de escena.

Respondido 14 ago 19, 19:08

"dependiendo de la presencia o ausencia de un tipo incorporado como clase base" => en realidad no se trata de "ausencia o presencia de un tipo incorporado como clase base" sino si la clase hereda - directamente o indirectamente - Desde object. IIRC hubo un punto en el tiempo en el que no todos los tipos incorporados fueron portados a clases de nuevo estilo todavía. - bruno desthuilliers

@brunodesthuilliers Mi impresión fue que todos los tipos integrados heredaron de object. Tengo un Python 2.2.3 y después de una verificación rápida no pude encontrar un delincuente, pero volveré a redactar la respuesta más tarde para dejarla más clara. Sin embargo, estaría interesado si pudiera encontrar un ejemplo, mi curiosidad se despierta. - Dimitris Fasarakis Hilliard

Con toda honestidad (consulte el "IIRC" en mi comentario anterior), no estoy un 101% seguro de este punto (si todos los tipos integrados ya se convirtieron en clases de estilo nuevo cuando se introdujeron las clases de estilo nuevo), podría ser simple incorrecto, o esto podría haber afectado solo a algunos de los tipos de lib estándar (pero no integrados). Sin embargo, creo que debería ser mejor aclarar que lo que hace que una clase de estilo nuevo sea object en sus bases. - bruno desthuilliers

staticmethod y classmethod funciona bien incluso en clases de estilo antiguo. property sorta trabaja para lectura en las clases de estilo antiguo, simplemente no intercepta las escrituras (por lo que si asigna el nombre, la instancia obtiene un atributo del nombre de pila que oculta la propiedad). También tenga en cuenta que __slots__La mejora de la velocidad de acceso a los atributos se trata principalmente de deshacer la pérdida en la que incurre el acceso a los atributos de clase de estilo nuevo, por lo que no es realmente un punto de venta de clases de estilo nuevo (aunque el ahorro de memoria es un punto de venta). - ShadowRanger

3 Python

  • class MyClass(object): = Clase de nuevo estilo
  • class MyClass: = Clase de nuevo estilo (hereda implícitamente de object)

2 Python

  • class MyClass(object): = Clase de nuevo estilo
  • class MyClass: = CLASE ANTIGUA

Explicación:

Al definir clases base en Python 3.x, se le permite eliminar el object de la definición. Sin embargo, esto puede abrir la puerta a un problema muy difícil de rastrear ...

Python introdujo clases de estilo nuevo en Python 2.2, y ahora las clases de estilo antiguo son bastante antiguas. La discusión de las clases de estilo antiguo es enterrado en los documentos 2.xe inexistente en los documentos 3.x.

El problema es, 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 incorpore sin saberlo definiciones de clase de estilo 3.x en código 2.x terminará con algunos objetos base seriamente desactualizados. Y debido a que las clases de estilo antiguo no están en el radar de nadie, es probable que no sepan qué los golpeó.

Así que deletree el camino largo y ahórrese las lágrimas a un desarrollador 2.x.

Respondido 19 Abr '20, 12:04

"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 a un problema muy difícil de rastrear ..." ¿A qué problemas se refiere? - Aidis

@Aidis: Creo que quieren decir que el código que se ejecuta tanto en Py2 como en Py3 estaría bien en Py3, pero se rompería en Py2 si se basa en características de clase de nuevo estilo. Personalmente, si estoy escribiendo un código así, omito la herencia explícita y solo pongo __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 tengan un nuevo estilo de forma predeterminada, y en Py3, se ignora por completo (solo una variable global aleatoria), por lo que es inofensivo. - ShadowRanger

Ahora que Python 2 es obsoleto, ¿eliminarlos de la órbita? - endolito

Sí, este es un objeto de '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. Ver este artículo para obtener una buena descripción de lo que es una nueva clase de estilo.

SO enlace para una descripción de las diferencias: ¿Cuál es la diferencia entre las clases de estilo antiguo y de estilo nuevo en Python?

Respondido 27 Oct 17, 19:10

+1 esto. Tenga en cuenta que las clases de estilo antiguo se han ido en Python 3, por lo que solo necesita heredar de object en Python 2. - user395760

Ésta no es una respuesta real. Solo hace referencia a otros artículos. Creo que la respuesta de Yarin debería aceptarse como la respuesta a esta pregunta. - alwbtc

@alwbtc: Esta respuesta también tiene algo nuevo. Por ejemplo, la mención de "super ()" me llevó a otro importante [aquí] (stackoverflow.com/questions/576169/… ). - ViFI

Historia de Aprende Python de la manera difícil:

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 tenían que soportarla. Para solucionar el problema, necesitaban un estilo de "nueva clase" para que las "clases antiguas" siguieran funcionando, pero puedes 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 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, en realidad es una clase, pero no olvides 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 object clase o de otra clase que heredó 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 Old Style no hereda de ninguna otra clase, sin embargo, las clases Old Style pueden, por supuesto, heredarse unas de otras. Heredar de objeto garantiza que cierta funcionalidad esté disponible en cada clase de Python. Se introdujeron nuevas clases de estilo en Python 2.2

Respondido el 17 de diciembre de 17 a las 08:12

Llamar a la clase raíz object no es tan confuso y, de hecho, es bastante estándar. Smalltalk tiene una clase raíz llamada Objecty una metaclase raíz llamada Class. ¿Por qué? Porque, al igual que 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 la gente usa hoy y que tienen una clase raíz usan alguna variación de Object como el nombre, no solo Python. - abarnert

Sí, es histórico. Sin él, crea una clase de estilo antiguo.

Si utiliza type() en un objeto de estilo antiguo, solo obtiene "instancia". En un objeto de estilo nuevo, obtienes su clase.

Respondido 15 Feb 18, 14:02

Además, si usas type() en una clase de estilo antiguo, obtienes "classobj" en lugar de "type". - Joel Sjogren

La sintaxis de la declaración de creación de clases:

class <ClassName>(superclass):
    #code follows

En ausencia de otras superclases de las que desee heredar específicamente, la superclass siempre debe 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 nuevo estilo 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 lo explícito siempre es mejor que lo implícito (infierno)

Referencia

Respondido 20 Oct 16, 06:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.