2013-11-20 3 views
4

Я хотел бы объявить иерархию пользовательских исключений в Python. Тем не менее, я бы хотел, чтобы мой пользовательский класс верхнего уровня (TransactionException) был абстрактным. То есть, я намереваюсь TransactionException указать методы, которые должны определять его подклассы. Однако TransactionException никогда не должен быть создан или создан.Можно ли объявить абстрактное исключение в Python?

У меня есть следующий код:

from abc import ABCMeta, abstractmethod 

class TransactionException(Exception): 
    __metaclass__ = ABCMeta 

    @abstractmethod 
    def displayErrorMessage(self): 
     pass 

Однако приведенный выше код позволяет мне экземпляр TransactionException ...

a = TransactionException() 

В этом случае a не имеет смысла, и вместо этого следует сделать исключение , Следующий код удаляет тот факт, что TransactionException является подклассом Exception ...

from abc import ABCMeta, abstractmethod 

class TransactionException(): 
    __metaclass__ = ABCMeta 

    @abstractmethod 
    def displayErrorMessage(self): 
     pass 

Этого код правильно запрещающим экземпляр, но теперь я не могу поднять подкласс TransactionException, потому что это не Exception больше.

Можно ли определить абстрактное исключение в Python? Если да, то как? Если нет, почему бы и нет?

ПРИМЕЧАНИЕ: Я использую Python 2.7, но с радостью соглашусь ответить на Python 2.x или Python 3.x.

ответ

2

Отличный ответ на эту тему от Alex Martelli here. В сущности, это приводит к тому, что при использовании абстрактных методов ведут себя как инициализаторы объектов (__init__) различных базовых классов (object, list, и, предположим, Exception).

Когда абстрактный класс наследует от object (который по умолчанию, если нет другого базового класса не дается), это __init__ метода установлено, что из object-х, который выполняет тяжелую-лифтинг в проверке, если все абстрактные методы были реализованы.

Если абстрактный класс наследуется от другого базового класса, он получит этот метод класса __init__. Другие классы, такие как list и Exception, похоже, не проверяют реализацию абстрактного метода, поэтому их экземпляры разрешены.

Другой ответ предлагает предлагаемое решение для этого. Конечно, другой вариант, который у вас есть, - это просто признать, что абстрактный класс будет реалистичным и попытаться отговорить его.

4
class TransactionException(Exception): 

    def __init__(self, *args, **kwargs): 
     raise NotImplementedError('you should not be raising this') 


class EverythingLostException(TransactionException): 

    def __init__(self, msg): 
     super(TransactionException, self).__init__(msg) 


try: 
    raise EverythingLostException('we are doomed!') 
except TransactionException: 
    print 'check' 

try: 
    raise TransactionException('we are doomed!') 
except TransactionException: 
    print 'oops' 
+1

Строго говоря, вы все еще можете создать экземпляр 'TransactionException', вы просто не можете его инициализировать (' exc = TransactionException .__ new __ (TransactionException) '). Но это, вероятно, в духе того, чего хочет OP. – chepner

Смежные вопросы