본문 바로가기
개발/PYTHON

abc 추상클래스

by 로그인시러 2017. 7. 4.

만약 아래와 같이 BaseClass를 상속받는 클래스에 실수로 func2를 구현 안했다면 어떻게 될까.


class DerivedClass3(BaseClass):

    def func1(self):

        print "FUNC1 in Derived3"


    """

    func2 method is not implented yet..

    """


 물론 엄마 클래스인 BaseClass의 func2 메서드를 실행하게 될 것이며 엄마클래스의 func2 메서드에서는 이를 pass 만 해놓도록 구현한 상태이기 때문에 아무것도 하지 않고 넘어갈 것이다. 이렇게 되면 나중에 이 부분의 구현을 추가 해야 된다는 사실을 잊고 넘어갈 수 있고, 추후 이로 인한 side effect 가 생길 여지가 있다. 


 그럼 이런 불상사를 피하기 위해 아래와 같이 BaseClass에 에러 호출부분을 추가해 보자.


 class BaseClass:

    def func1(self):

        raise NotImplementedError()


    def func2(self):

        raise NotImplementedError()

 

이렇게 해놓으면 BaseClass를 상속받을 파생 클래스에서 해당 메서드의 구현을 하지 않는다면, 자동으로 BaseClass의 메서드를 호출할 것이고,  NotImplentedError 를 발생시킬 것이다.


FUNC1 in Dervied3

Traceback (most recent call last):

  File "D.py", line 5, in <module>

    _m.func2()

  File "/home/ubuntu/BaseClass.py", line 6, in func2

    raise NotImplementedError()

NotImplementedError


즉, 조금 더 엄격하게 상속 클래스들을 관리할 수 있게 되며, 추후 유지보수를 용이하게 할 수 있다. 

하지만, 이것보다 더 Strict 한 방식을 제공하는 것이 오늘 알아볼 ABC 클래스이다.




ABC (Abstract Base Class)


아래는 BaseClass에 abc를 적용한 예이다.


import abc 


class BaseClass:


    __metaclass__ = abc.ABCMeta


    @abc.abstractmethod

    def func1(self):

        pass


    @abc.abstractmethod

    def func2(self):

        pass



추상화 시키고자 하는 메서드에 데코레이터로 @abstractmethod 를 선언해 주면 된다.

이렇게 적용하게 되면, BaseClass를 상속받는 모든 파생 클래스에서 해당 메서드를 선언해서 구현하지 않으면, 에러를 발생시키게 된다.


Traceback (most recent call last):

  File "D.py", line 2, in <module>

    _m = getattr(__import__(cls_name, fromlist=[]), cls_name)()

TypeError: Can't instantiate abstract class DerivedClass3 with abstract methods func2


그렇다면, ABC를 사용하는 것과 NotImplementedError 를 메서드마다 선언해 놓는 것은 어떤 차이가 있을까.


첫째로, abc 클래스를 이용하게 되면, 해당 BaseClass 는 인스턴스화 될 수 없다. 단지 파생 클래스 구현을 위한 추상화 기능 제공 역할을 하게 될 뿐이다.


>>> from BaseClass import BaseClass

>>> 

>>> base = BaseClass()

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: Can't instantiate abstract class BaseClass with abstract methods func1, func2


 두번째, abc 클래스를 이용하게 될 경우 에러 발생 시점이 다르다.

 메서드에 raise를 이용해 NotImplementedError 를 선언해 놓은 경우에는 런타임 상황에서 해당 메서드가 실제로 호출이 되는 시점에 에러를 발생시키게 되지만, abc 를 이용하는 경우에는 해당 모듈이 import 되는 순간부터 에러를 발생시키게 된다. 즉, abc 클래스를 이용하는 경우 조금 더 strict 한 모듈 관리가 가능해 진다는 점이다.


Traceback (most recent call last):

  File "D.py", line 2, in <module>

    _m = getattr(__import__(cls_name, fromlist=[]), cls_name)()

TypeError: Can't instantiate abstract class DerivedClass3 with abstract methods func2


위에서 보는것 같이 에러 발생 시점이 해당 모듈을 import하는 순간 발생 된다.




출처: http://bluese05.tistory.com/61 [ㅍㅍㅋㄷ]

'개발 > PYTHON' 카테고리의 다른 글

scraping ajax pages  (0) 2017.07.06
로깅모듈[펌]  (0) 2017.07.03
python comprehension [펌]  (0) 2017.07.03
mysql 접속  (0) 2017.06.30
python 웹크롤링  (0) 2017.06.28

댓글