Requerir explícitamente atributo en descendiente de la clase base de python.
Tengo una clase base abstracta de la cual solo estoy mostrando una pequeña parte aquí, para ilustrar mi problema.
La clase base abstracta “A” a continuación tiene una propiedad “onemore” que utiliza el atributo de instancia “val”. A continuación, hay subclases “B” y “C”, que proporcionan este atributo de formas distintas (pero ambas válidas).
Hasta aquí todo bien:
from abc import ABC, abstractmethod
class A(ABC):
@property
def onemore(self) -> int:
return self.val + 1
class B(A):
def __init__(self, value):
self._val = value
val = property(lambda self: self._val)
class C(A):
def __init__(self, value):
self.val = value
b = B(32)
b.onemore # 33
c = C(54)
c.onemore # 55
Ahora aquí está mi pregunta: ¿hay alguna manera de definir “A” de tal manera que sea más claro que las subclases deben implementar “val”? Como se define anteriormente, esto es difícil de pasar por alto, especialmente si “A” tiene muchos más métodos.
Intenté esto:
class A(ABC):
@property
@abstractmethod
def val(self) -> int:
...
@property
def onemore(self) -> int:
return self.val + 1
Sin embargo, esta definición es demasiado estricta: no quiero exigir que las subclases implementen “val” como una propiedad, solo quiero que lo tengan como un atributo (legible). En otras palabras, quiero que “C” sea una subclase válida, lo cual no es el caso aquí: esta definición no funciona con la forma en que “C” proporciona “self.val” (TypeError: No se puede instanciar una clase abstracta C con el método abstracto val).
¿Alguna idea?
PD: He visto esta pregunta (https://stackoverflow.com/q/2736255/2302262), que es similar, pero no resuelve el TypeError que estoy obteniendo.
davy.ai
Una posible solución para dejar más claro que las subclases necesitan implementar
val
es definirla como un atributo abstracto enA
en lugar de como una propiedad abstracta:De esta manera, las subclases deberán definir
val
como un atributo, pero no será necesario que sea una propiedad. Esto resuelve el problema conC
, ya que puede proporcionarval
como un atributo de instancia regular. El código actualizado se vería así:Esto generará un
TypeError
si una subclase deA
no proporciona un atributoval
.