Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python 추상 기본 클래스(ABC) 완벽 정리: 개념부터 실전 예제까지

하나 이상의 추상 메서드(abstract method)를 포함하는 클래스를 추상 클래스(abstract class)라고 합니다. 추상 메서드란 선언만 존재하고 구현 내용이 없는 메서드를 의미합니다. 추상 클래스는 직접 인스턴스화할 수 없으며, 추상 메서드는 반드시 하위 클래스에서 구현해야 합니다.

추상 기본 클래스(ABC)가 필요한 이유

추상 기본 클래스(Abstract Base Class, ABC)는 hasattr() 같은 다른 기법으로는 다루기 어색하거나 미묘하게 잘못된 결과를 낼 수 있는 상황(예: 매직 메서드 처리)에서 인터페이스를 명확하게 정의할 수 있는 방법을 제공합니다.

ABC의 중요한 특징 중 하나는 가상 서브클래스(virtual subclass) 개념입니다. 가상 서브클래스는 특정 클래스를 상속하지 않지만, isinstance()issubclass() 함수가 해당 클래스로 인식하도록 등록된 클래스입니다.

Python에는 이미 많은 내장 ABC가 존재합니다.

  • collections.abc 모듈: Iterator, Generator, Set, Mapping 등 자료구조 관련 ABC 제공
  • numbers 모듈: 숫자 데이터 타입을 위한 기본 클래스들의 집합인 숫자 타워(numeric tower) 정의
  • abc 모듈: 사용자 정의 추상 기본 클래스를 만들기 위한 기반 인프라 제공

@abstractmethod 데코레이터로 추상 메서드 선언하기

abc 모듈은 기본 클래스의 메서드에 @abstractmethod 데코레이터를 붙여 추상 메서드로 표시하는 방식으로 동작합니다. 이러한 추상 기본 클래스를 상속한 구체 클래스(concrete class)는 추상 메서드를 오버라이딩하여 구현해야 합니다.

ABCMeta 메타클래스 활용 예제

abc 모듈은 추상 기본 클래스를 정의하기 위한 메타클래스인 ABCMeta를 제공합니다. 아래 예제는 Shape 클래스를 ABCMeta를 사용한 추상 기본 클래스로 정의하고, area() 메서드를 추상 메서드로 선언합니다.

import abc
class Shape(metaclass=abc.ABCMeta):
   @abc.abstractmethod
   def area(self):
      pass
class Rectangle(Shape):
   def __init__(self, x,y):
      self.l = x
      self.b=y
   def area(self):
      return self.l*self.b
r = Rectangle(10,20)
print ('area: ',r.area())

Rectangle 클래스는 Shape를 부모로 삼아 추상 메서드 area()를 구현합니다. 구체 클래스이므로 인스턴스를 생성할 수 있고, 구현된 area() 메서드를 호출할 수 있습니다.

주의: 추상 기본 클래스에는 여러 개의 추상 메서드가 존재할 수 있습니다. 이 경우 자식 클래스는 모든 추상 메서드를 구현해야 하며, 하나라도 누락되면 TypeError가 발생합니다.

ABC 헬퍼 클래스 사용하기

abc 모듈은 ABCMeta 대신 사용할 수 있는 ABC 헬퍼 클래스도 제공합니다. 코드가 더 간결해지므로 실무에서 널리 사용됩니다.

class Shape(abc.ABC):
   @abc.abstractmethod
   def area(self):
      pass

register()로 가상 서브클래스 등록하기

클래스를 추상 기본 클래스의 서브클래스로 만들지 않고도, register() 메서드를 사용해 가상 서브클래스로 등록할 수 있습니다.

class Shape(abc.ABC):
   @abc.abstractmethod
   def area(self):
      pass
@Shape.register
class Rectangle():
   def __init__(self, x,y):
      self.l = x
      self.b = y
   def area(self):
      return self.l*self.b

이렇게 등록된 RectangleShape를 상속하지 않았음에도 isinstance(r, Shape)True를 반환합니다.

추상 클래스메서드와 추상 스태틱메서드

추상 기본 클래스 안에서는 @abstractclassmethod@abstractstaticmethod 데코레이터를 사용해 각각 추상 클래스메서드와 추상 스태틱메서드도 정의할 수 있습니다. 이를 통해 인터페이스 설계 시 더욱 유연하고 일관성 있는 API를 만들 수 있습니다.