Python的实际确实有抽象类与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
>>>
在另一方面,根本问题“是这样的Python的”是有点难说。如果你的意图是提供抽象基类,以便稍后检查以确保值继承它,那么不,那不是特别的pythonic,即使可以制作任意类型的基类的抽象子类。另一方面,提供基于具体子类中提供的实现来实现某些功能的抽象基类是完全正确的。例如,collections.Sequence
和collections.Mapping
对于像列表和类似词典这样的列表可以做到这一点;子类可以提供__getitem__
,可以免费获得__contains__
等。
对于某些情况,您绝对不应该使用assert()
,但要记录代码的期望值;如果断言实际上可能失败,则不应该使用断言。优化的python(python -O script.py
)不检查断言。
编辑:更多的论述:
如果您正在检查值的类型:
def foo(bar):
if not isinstance(bar, AbstractBaz):
raise ValueError, ("bar must be an instance of AbstractBaz, "
"got %s" % type(bar))
如果由于某种原因,你不能使用@abstractmethod
,但还是要这个效果,你应提高NotImplementedError
。您可能想要这样做,因为您确实需要该类的实例,其中一些可能不需要实现可选功能。你仍然应该考虑通过super()
调用函数的可能性。初步估计,这可能看起来像这样。
class Foo(object):
def bar(self, baz):
if self.bar.im_func == Foo.bar.im_func:
raise NotImplementedError, "Subclasses must implement bar"
“Python避免了编译器强制的接口声明,因为它们试图在代码中记录一种通过超语言学方式更好地执行的合同。” WTF?请澄清此声明,这可能会使其他人更有帮助。 – hiwaylon
此外,如果您要求图书馆的用户在课堂上实施混合教学的方法,那么ABCs和/或抽象方法在鸭子打字世界中是完全有效的。谁在乎,如果它是适当的软件工程,它是“不扩张的”,还是反对特定社区的灌输信仰。看看TokenMacGuy的回答,忽略这个人。 – hiwaylon