Расширение как абстрактного базового класса, так и класса, производного от «объекта», работает так, как и следовало ожидать: если вы не реализовали все абстрактные методы и свойства, вы получите ошибку.
Как ни странно, замена класса, производного от объекта, классом, расширяющим «Exception», позволяет создавать экземпляры классов, которые не реализуют все требуемые абстрактные методы и свойства.
Например:
import abc
# The superclasses
class myABC( object ):
__metaclass__ = abc.ABCMeta
@abc.abstractproperty
def foo(self):
pass
class myCustomException( Exception ):
pass
class myObjectDerivedClass( object ):
pass
# Mix them in different ways
class myConcreteClass_1(myCustomException, myABC):
pass
class myConcreteClass_2(myObjectDerivedClass, myABC):
pass
# Get surprising results
if __name__=='__main__':
a = myConcreteClass_1()
print "First instantiation done. We shouldn't get this far, but we do."
b = myConcreteClass_2()
print "Second instantiation done. We never reach here, which is good."
... дает ...
First instantiation done. We shouldn't get this far, but we do.
Traceback (most recent call last):
File "C:/Users/grahamf/PycharmProjects/mss/Modules/mssdevice/sutter/sutter/test.py", line 28, in <module>
b = myConcreteClass_2()
TypeError: Can't instantiate abstract class myConcreteClass_2 with abstract methods foo
Я знаю, что «Exception» и, следовательно, «myCustomException» не имеют атрибута «foo», так почему же мне сходит с рук создание экземпляра «myCustomException»?
РЕДАКТИРОВАТЬ: Для справки, это хакерский обходной путь, которым я в конечном итоге воспользовался. Не совсем эквивалентно, но подходит для моих целей.
# "abstract" base class
class MyBaseClass( Exception ):
def __init__(self):
if not hasattr(self, 'foo'):
raise NotImplementedError("Please implement abstract property foo")
class MyConcreteClass( MyBaseClass ):
pass
if __name__=='__main__':
a = MyConcreteClass()
print "We never reach here, which is good."