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