Python en realidad hace tienen clases abstractas con métodos abstact:
>>> import abc
>>>
>>> class IFoo(object):
... __metaclass__ = abc.ABCMeta
...
... @abc.abstractmethod
... def foo(self):
... pass
...
>>> foo = IFoo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Cant instantiate abstract class IFoo with abstract methods foo
>>> class FooDerived(IFoo):
... pass
...
>>> foo = FooDerived()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Cant instantiate abstract class FooDerived with abstract methods foo
>>> class FooImplements(FooDerived):
... def foo(self):
... print "foo'ed"
...
>>> foo = FooImplements()
>>> foo.foo()
foo'ed
>>>
Por otra parte, la cuestión fundamental de "es este Pythonic" es un poco más difícil de decir. Si su intención es proporcionar la clase base abstracta para que luego pueda verificar que los valores hereden de ella, entonces no, eso no es particularmente pitónico, aunque es posible hacer tipos arbitrarios de subclases abstractas de su clase base. Por otro lado, está perfectamente bien proporcionar una clase base abstracta que implemente alguna funcionalidad basada en la implementación provista en subclases concretas. Por ejemplo, collections.Sequence
y collections.Mapping
hacen esto para las clases like y dict like; las subclases pueden proporcionar __getitem__
y pueden obtener __contains__
y otras de forma gratuita.
Por cierto, nunca debe usar assert()
excepto para documentar las expectativas del código; Si es posible que la afirmación falle, no debería usar una afirmación. La versión optimizada de Python (python -O script.py
) no verifica las aserciones.
Editar: más exposición:
Si está mirando el tipo de un valor:
def foo(bar):
if not isinstance(bar, AbstractBaz):
raise ValueError, ("bar must be an instance of AbstractBaz, "
"got %s" % type(bar))
Si por alguna razón no se puede utilizar @abstractmethod
, pero todavía quiere ese efecto, se debe aumentar NotImplementedError
. Es posible que desee hacerlo porque realmente desea instancias de esa clase, algunas de las cuales tal vez no necesiten implementar funcionalidad opcional. Aún debe tener en cuenta la posibilidad de que se haya llamado a la función a través del super()
. Para una primera aproximación, podría verse así.
class Foo(object):
def bar(self, baz):
if self.bar.im_func == Foo.bar.im_func:
raise NotImplementedError, "Subclasses must implement bar"
"Python evita las declaraciones de interfaz impuestas por el compilador cuando intentan documentar, en código, un contrato que se aplica mejor a través de medios extralingüísticos". WTF? Por favor aclare esta afirmación, podría ayudar a otros. – hiwaylon
Además, el ABC y/o métodos abstractos son perfectamente válidos en el mundo de tipado de pato si requiere que los usuarios de su biblioteca implementen un método de, por ejemplo, una mezcla en clase. A quién le importa si es "antipático" o contrario a las creencias adoctrinadas de una comunidad en particular si se trata de una ingeniería de software adecuada. Echa un vistazo a la respuesta de TokenMacGuy a continuación e ignora a este tipo. – hiwaylon