2013-11-20 74 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是沒有意義的,而應借鑑異常。下面的代碼刪除的事實,TransactionExceptionException一個子類...

from abc import ABCMeta, abstractmethod 

class TransactionException(): 
    __metaclass__ = ABCMeta 

    @abstractmethod 
    def displayErrorMessage(self): 
     pass 

此代碼正確禁止實例化,但現在,因爲它不是一個Exception下去,我不能提高TransactionException一個子類。

可以在Python中定義一個抽象異常嗎?如果是這樣,怎麼樣?如果不是,爲什麼不呢?

注意:我使用Python 2.7,但會很樂意接受Python 2.x或Python 3.x的答案。

回答

2

Alex Martelli here有很好的答案。本質上,它涉及當抽象方法存在時,各種基類(objectlist和我推測,Exception)的對象初始值設定項(__init__)如何表現。

當一個抽象類從object繼承(這是默認的,如果沒有其他基類中給出),它的__init__方法被設定爲的object的,這在檢查是否所有的抽象方法進行繁重工作已經實施。

如果抽象類繼承自不同的基類,它將得到該類的方法'__init__。其他類,如listException,看起來,不檢查抽象方法實現,這就是爲什麼實例化它們是允許的。

另一個答案爲此提供了一個建議的解決方法。當然,你擁有的另一個選擇是簡單地接受抽象類將是可實例化的,並試圖阻止它。

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