2014-10-18 3 views
1

제가 알기로, 파이썬에서 abc 모듈을 사용하여 (다른 멋진 속성들 사이에서) 인스턴스화 할 수없는 추상 클래스를 만들 수 있습니다. 이 응용 프로그램에 대한 다양한 종료 코드를 나타내는 Exception 클래스의 계층 구조를 만들려면이 사용하려고했지만 난 그 일이 싶지 않아도 내 기본 클래스를 인스턴스화 할 수 있습니다. 여기에 문제 보여 일부 코드입니다 :파이썬에서 추상 추상 클래스를 인스턴스화 할 수있는 이유는 무엇입니까?

#!/usr/bin/env python3 

import abc 

class ExitCodeException(Exception): 
    __metaclass__ = abc.ABCMeta 

    def __init__(self, message): 
     super().__init__() 
     self._message = message 

    @abc.abstractmethod 
    def getExitCode(self): 
     """Return the exit code for this exception""" 
     return 

class FatalException(ExitCodeException): 
    def getExitCode(self): 
     return 1 

raise ExitCodeException("Oh no!") 

내가 ExitCodeException 인스턴스화 할 수 없다는 말을 예외로 종료하는 내 프로그램을 기다리고 있었다,하지만 대신 난 그냥 경우를 기대할 표준 스택 추적을 얻을 ExitCodeException weren 히 초록 :

Traceback (most recent call last) 
    File "./email2pdf_classexception", line 21, in <module> 
    raise ExitCodeException("Oh no!") 
__main__.ExitCodeException 

어떻게 해결할 수 있습니까?

+3

Python3에서 키워드 구문을 사용해야합니다 :'class ExitCodeException (Exception, metaclass = abc.ABCMeta) :'. 그러나 이것은 당신의 문제를 해결하기에 충분하지 않습니다. 'Exception' 기본 클래스는 인스턴스화를 가능하게합니다 - 그것없이 모든 것이 예상대로 작동합니다. 그러나이 기본 클래스에서 throw 가능한 예외를 파생시키려는 경우 문제가 해결되지 않는다고 생각합니다. – BartoszKP

+2

먼저, 메타 클래스를 정의하는 구문이 Python3에서 변경되었습니다. 클래스 정의 (ref : https://docs.python.org/3.3/reference/datamodel.html#customizing-class-creation)에 키워드 인수 ('metaclass')를 전달해야합니다. 둘째, ABC는 ABC가 아닌 기본 클래스를 가질 수 없습니다. 따라서 ABC가 'ExitCodeException'이되게하려면 'Exception' (ABC가 아님)을'ExitCodeException'의 기본 클래스로 사용할 수 없습니다. 코드 작성을위한 직접적인 방법은 없다고 생각합니다. –

+1

기본 클래스를 인스턴스화 할 수없는 이유는 무엇입니까? 인스턴스화하고 싶지 않으면 인스턴스화하지 마십시오. 파이썬으로 자바를 작성하려고하는 것처럼 느껴진다. –

답변

2

위의 @BartoszKP 및 @Debanshu Kundu의 의견에서 설명한 것처럼 콘크리트 수퍼 클래스 Exception이 여기에서 문제를 일으키는 원인입니다.

#!/usr/bin/env python3 

class ExitCodeException(Exception): 
    def __new__(cls, *args, **kwargs): 
     if cls is ExitCodeException: 
      raise NotImplementedError("Base class may not be instantiated") 
     return Exception.__new__(cls, *args, **kwargs) 

    def __init__(self, message): 
     super().__init__() 
     self._message = message 

    def getExitCode(self): 
     """Return the exit code for this exception""" 
     return 

class FatalException(ExitCodeException): 
    def getExitCode(self): 
     return 1 

raise FatalException("Oh no!") 

이 작품 : 따라서, 나는 (내가 알기로,이 파이썬 2에서 패턴의 이전 스타일이지만, 여전히 유효한 것) 작동하는 것 같다 약간 다른 패턴으로 왔어요 의도 한대로; ExitCodeException을 직접 인스턴스화하도록 코드를 변경하면 오류가 발생합니다.

관련 문제