¿Cómo puedo hacer un resumen de clase o método en Python?
Intenté redefinir __new__()
así:
class F:
def __new__(cls):
raise Exception("Unable to create an instance of abstract class %s" %cls)
pero ahora si creo una clase G
que hereda de esta F
manera:
class G(F):
pass
entonces tampoco puedo crear instancias G
, ya que llama al __new__
método de su superclase.
¿Hay una mejor manera de definir una clase abstracta?
python
class
inheritance
abstract-class
abstract
Martin Thoma
fuente
fuente
Respuestas:
Usa el
abc
módulo para crear clases abstractas. Use elabstractmethod
decorador para declarar un resumen de método y declare un resumen de clase utilizando una de tres formas, dependiendo de su versión de Python.En Python 3.4 y superior, puede heredar de
ABC
. En versiones anteriores de Python, debe especificar la metaclase de su clase comoABCMeta
. Especificar la metaclase tiene una sintaxis diferente en Python 3 y Python 2. Las tres posibilidades se muestran a continuación:De cualquier forma que utilice, no podrá crear una instancia de una clase abstracta que tenga métodos abstractos, pero podrá crear una instancia de una subclase que proporcione definiciones concretas de esos métodos:
fuente
@abstractmethod
hace que sea para que la función decorado debe ser anulado antes de la clase se pueden crear instancias. De los documentos:A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden.
@abstractmethod
para__init__
el método, así, ver stackoverflow.com/q/44800659/547270La forma de hacer esto de la vieja escuela (antes de PEP 3119 ) es simplemente
raise NotImplementedError
en la clase abstracta cuando se llama a un método abstracto.Esto no tiene las mismas buenas propiedades que el uso del
abc
módulo. Todavía puede crear una instancia de la clase base abstracta en sí, y no encontrará su error hasta que llame al método abstracto en tiempo de ejecución.Pero si se trata de un pequeño conjunto de clases simples, tal vez con solo unos pocos métodos abstractos, este enfoque es un poco más fácil que tratar de leer la
abc
documentación.fuente
Aquí hay una manera muy fácil sin tener que lidiar con el módulo ABC.
En el
__init__
método de la clase que desea que sea una clase abstracta, puede verificar el "tipo" de sí mismo. Si el tipo de self es la clase base, entonces la persona que llama está tratando de crear una instancia de la clase base, por lo que genera una excepción. Aquí hay un ejemplo simple:Cuando se ejecuta, produce:
Esto muestra que puede crear una instancia de una subclase que hereda de una clase base, pero no puede crear una instancia de la clase base directamente.
fuente
La mayoría de las respuestas anteriores eran correctas, pero aquí está la respuesta y el ejemplo para Python 3.7. Sí, puedes crear una clase y método abstractos. Solo como recordatorio, a veces una clase debe definir un método que lógicamente pertenece a una clase, pero esa clase no puede especificar cómo implementar el método. Por ejemplo, en las siguientes clases de Padres y Bebés, ambos comen, pero la implementación será diferente para cada uno porque los bebés y los padres comen un tipo diferente de comida y la cantidad de veces que comen es diferente. Entonces, las subclases de método eat anulan AbstractClass.eat.
SALIDA:
fuente
import abc
sea inútil.Este estará trabajando en Python 3
fuente
Como se explica en las otras respuestas, sí, puede usar clases abstractas en Python usando el
abc
módulo . A continuación voy a dar un ejemplo real utilizando abstracta@classmethod
,@property
y@abstractmethod
(usando Python 3.6 o superior). Para mí, generalmente es más fácil comenzar con ejemplos que puedo copiar y pegar fácilmente; Espero que esta respuesta también sea útil para otros.Primero creemos una clase base llamada
Base
:Nuestra
Base
clase siempre tendrá unfrom_dict
classmethod
, aproperty
prop1
(que es de solo lectura) y aproperty
prop2
(que también se puede configurar), así como una función llamadado_stuff
. Cualquier clase en la que se cree ahoraBase
tendrá que implementar todo esto para métodos / propiedades. Tenga en cuenta que para que un método sea abstracto, se requieren dos decoradores,classmethod
y abstractoproperty
.Ahora podríamos crear una clase
A
como esta:Todos los métodos / propiedades requeridos se implementan y, por supuesto, también podemos agregar funciones adicionales que no son parte de
Base
(aquí:)i_am_not_abstract
.Ahora podemos hacer:
Como lo deseamos, no podemos establecer
prop1
:volverá
También nuestro
from_dict
método funciona bien:Si ahora definimos una segunda clase
B
como esta:e intenté instanciar un objeto como este:
obtendremos un error
enumerando todas las cosas definidas en las
Base
que no implementamosB
.fuente
También esto funciona y es simple:
fuente
También puede aprovechar el método __nuevo__ para su ventaja. Acabas de olvidar algo. El método __new__ siempre devuelve el nuevo objeto, por lo que debe devolver el nuevo método de su superclase. Haz lo siguiente.
Al usar el nuevo método, debe devolver el objeto, no la palabra clave None. Eso es todo lo que te perdiste.
fuente
Encuentro la respuesta aceptada, y todas las demás extrañas, ya que pasan
self
a una clase abstracta. Una clase abstracta no se instancia, por lo que no puede tener unself
.Intenta esto, funciona.
fuente
fuente
En su fragmento de código, también puede resolver esto proporcionando una implementación para el
__new__
método en la subclase, de la misma manera:Pero este es un truco y te aconsejo que no lo hagas, a menos que sepas lo que estás haciendo. Para casi todos los casos, le aconsejo que use el
abc
módulo, que otros antes que yo han sugerido.También cuando se crea una nueva clase (base), que sea subclase
object
, así:class MyBaseClass(object):
. No sé si ya es tan significativo, pero ayuda a mantener la coherencia de estilo en su códigofuente
Solo una adición rápida a la respuesta de la vieja escuela de @ TimGilbert ... puede hacer que el método init () de su clase base abstracta arroje una excepción y eso evitaría que se instanciara, ¿no?
fuente