abc — 추상 기본 클래스

abc — 추상 기본 클래스 (Abstract Base Classes)

이 모듈은 파이썬에서 추상 기본 클래스(ABC) 를 정의하기 위한 인프라를 제공해요. PEP 3119에 정리되어 있는 개념이고, 왜 파이썬에 추가됐는지는 해당 PEP를 보면 돼요. (숫자의 ABC 기반 타입 계층은 PEP 3141과 numbers 모듈을 참고하세요.)

collections 모듈에는 ABC에서 파생된 몇몇 구체 클래스가 있는데, 물론 더 파생시킬 수 있어요. 또 collections.abc 서브모듈에는 클래스나 인스턴스가 특정 인터페이스(예: hashable인지, mapping인지)를 제공하는지 검사하는 데 쓸 수 있는 ABC들이 있어요.

이 모듈은 ABC를 정의하기 위한 메타클래스 ABCMeta와, 상속을 통해 ABC를 더 쉽게 정의하게 해 주는 헬퍼 클래스 ABC를 제공해요.

출처: Python documentation

본문

class abc.ABC

ABCMeta를 메타클래스로 갖는 헬퍼 클래스예요. 이 클래스를 쓰면 가끔 헷갈리는 메타클래스 사용법을 피하고 간단히 ABC에서 상속받아 추상 기본 클래스를 만들 수 있어요.

from abc import ABC
class MyABC(ABC):
    pass

ABC의 타입은 여전히 ABCMeta이므로 ABC에서 상속하는 건 메타클래스 사용에 관한 평소 주의 사항이 필요해요. 다중 상속이 메타클래스 충돌로 이어질 수 있기 때문이에요. 대신 메타클래스 키워드로 ABCMeta를 직접 쓰는 방법도 있어요.

from abc import ABCMeta
class MyABC(metaclass=ABCMeta):
    pass

(3.4 추가)

class abc.ABCMeta

추상 기본 클래스를 정의하기 위한 메타클래스예요. 이 메타클래스로 ABC를 만들면 ABC를 직접 서브클래스로 만들 수 있고 그러면 mix-in 클래스처럼 동작해요. 관련 없는 구상 클래스(내장 클래스 포함)나 관련 없는 ABC를 "가상 서브클래스(virtual subclass)"로 등록(register) 할 수도 있어요. 이들의 후손은 내장 issubclass() 함수에 의해 등록 ABC의 서브클래스로 간주되지만, 등록 ABC는 그들의 MRO(메서드 해석 순서)에 나타나지 않고 등록 ABC가 정의한 메서드 구현도 (심지어 super()로도) 호출할 수 없어요.

ABCMeta 메타클래스로 만든 클래스는 다음 메서드를 가져요.

register(subclass)

subclass를 이 ABC의 "가상 서브클래스"로 등록해요.

from abc import ABC
class MyABC(ABC):
    pass
MyABC.register(tuple)
assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)

(3.3부터 등록된 서브클래스를 반환해 클래스 데코레이터로 쓸 수 있고, 3.4부터 get_cache_token()으로 register() 호출을 감지할 수 있어요.) 이 메서드는 추상 기본 클래스에서 오버라이드할 수도 있어요.

__subclasshook__(subclass)

(클래스 메서드로 정의해야 해요.) subclass가 이 ABC의 서브클래스로 간주되는지 확인해요. 즉 매번 register()를 호출하지 않고도 issubclass()의 동작을 더 세밀하게 커스터마이즈할 수 있어요. (이 클래스 메서드는 ABC의 __subclasscheck__() 메서드에서 호출돼요.) 이 메서드는 True, False 또는 NotImplemented를 반환해야 해요. True면 서브클래스로 간주되고, False면 보통은 맞아도 서브클래스로 간주되지 않으며, NotImplemented면 평소 메커니즘으로 서브클래스 검사를 계속해요.

@abc.abstractmethod

추상 메서드를 나타내는 데코레이터예요. 이 데코레이터를 쓰려면 클래스의 메타클래스가 ABCMeta이거나 그로부터 파생되어야 해요. ABCMeta에서 파생된 메타클래스를 가진 클래스는 모든 추상 메서드와 속성을 오버라이드하지 않으면 인스턴스화할 수 없어요. 추상 메서드는 일반적인 'super' 호출 메커니즘으로 호출할 수 있어요. @abstractmethod는 속성(property)과 descriptor의 추상 메서드 선언에도 쓸 수 있어요.

클래스에 추상 메서드를 동적으로 추가하거나, 생성 후 메서드/클래스의 추상 상태를 바꾸는 것은 update_abstractmethods() 함수로만 지원돼요. @abstractmethod는 일반 상속으로 파생된 서브클래스에만 영향을 주고, ABC의 register()로 등록된 "가상 서브클래스"에는 영향이 없어요.

@abstractmethod를 다른 메서드 descriptor와 조합해 쓸 때는 가장 안쪽 데코레이터로 적용해야 해요.

class C(ABC):
    @abstractmethod
    def my_abstract_method(self, arg1):
        ...
    @classmethod
    @abstractmethod
    def my_abstract_classmethod(cls, arg2):
        ...
    @staticmethod
    @abstractmethod
    def my_abstract_staticmethod(arg3):
        ...
    @property
    @abstractmethod
    def my_abstract_property(self):
        ...

추상 기본 클래스 메커니즘과 올바르게 상호작용하려면 descriptor는 __isabstractmethod__로 자신을 추상임을 표시해야 해요. 일반적으로 descriptor를 구성하는 메서드 중 하나라도 추상이면 이 속성은 True여야 해요. 내장 @property가 정확히 그렇게 동작해요.

참고: 자바의 추상 메서드와 달리, 파이썬의 추상 메서드는 구현을 가질 수 있어요. 이 구현은 오버라이드하는 클래스에서 super() 메커니즘으로 호출할 수 있어요. 협력적 다중 상속을 쓰는 프레임워크에서 super 호출의 종착점으로 유용할 수 있어요.

레거시 데코레이터

  • @abc.abstractclassmethod (3.2 추가, 3.3부터 deprecated): 내장 classmethod의 서브클래스로 추상 클래스메서드를 나타내요. @classmethod@abstractmethod를 함께 쓸 수 있어 이 데코레이터는 이제 불필요해요.
  • @abc.abstractstaticmethod (3.2 추가, 3.3부터 deprecated): 내장 staticmethod의 서브클래스로 추상 스태틱메서드를 나타내요. @staticmethod@abstractmethod를 함께 쓸 수 있어 이제 불필요해요.
  • @abc.abstractproperty (3.3부터 deprecated): 내장 property의 서브클래스로 추상 속성을 나타내요. @property@abstractmethod를 함께 쓸 수 있어 이제 불필요해요.

함수

  • abc.get_cache_token(): 현재 추상 기본 클래스 캐시 토큰을 반환해요. 토큰은 (동등성 검사를 지원하는) 불투명 객체로, 가상 서브클래스용 추상 기본 클래스 캐시의 현재 버전을 식별해요. 토큰은 어떤 ABC에서든 ABCMeta.register()가 호출될 때마다 바뀌어요. (3.4 추가)
  • abc.update_abstractmethods(cls): 추상 클래스의 추상 상태를 다시 계산하는 함수예요. 클래스의 추상 메서드가 생성된 후 구현되거나 변경됐을 때 호출해야 해요. 보통 클래스 데코레이터 안에서 호출해요. cls를 반환해 클래스 데코레이터로 쓸 수 있어요. clsABCMeta의 인스턴스가 아니면 아무것도 하지 않아요. 이 함수는 cls의 수퍼클래스가 이미 업데이트됐다고 가정하고 서브클래스는 업데이트하지 않아요. (3.10 추가)

[1] C++ 프로그래머라면 파이썬의 virtual base class 개념이 C++의 것과 같지 않다는 점을 알아두세요.

더 알아보기 (Learn more)