본문 바로가기

진리는어디에/Python

[Python] 클래스(class) #9 추상 클래스와 추상 메소드

이번 포스트는 파이썬 클래스 시리즈의 마지막 장으로 파이썬 클래스의 추상 클래스와 추상 메소드에 대해 알아보도록 하겠다. 이 강의는 이전에 배운 클래스 상속과 이어진다.

목차

  1. 파이썬 클래스 소개
  2. instance vs static
  3. dict vs slots
  4. property의 활용
  5. special method
  6. callable object
  7. 클래스 데코레이터(class decorator)
  8. 상속
  9. >> 추상 클래스와 추상 메소드

추상 클래스(abstract class)란?

파이썬은 추상 클래스(abstract class)를 제공한다. 추상 클래스란 구현 내용이 없고 메소드 목록만 가진 클래스이며, 추상클래스 자체로는 인스턴스화가 불가능 하다. 추상 클래스는 클래스의 메소드를 상속 받는 파생 클래스에게 구현하도록 강제하기 위해 사용 된다.

추상 클래스가 어떤 상황에서 사용되었을 때 우리에게 도움이 될지는 너무 다양한 상황과 제약 사항이 있어 한 장의 포스트에서 다루기엔 무리가 있고, 강의를 진행하면서 추상 클래스의 사용 예시에 대해 다시 언급하도록 하겠다. 이번 장에서는 추상클래스의 사용 문법에 초첨을 맞추도록 하겠다.

추상 클래스 문법

파이썬에서 추상 클래스를 사용하는 방법은 생각 보다 간단하다.

  • 가장 먼저 abc(abstract base class) 모듈의 ABC 클래스와 abstractmethod 데코레이터를 임포트한다.
  • 그리고 ABC 클래스를 상속 받은 추상 클래스를 정의하고
  • 파생 클래스에게 구현을 강제할 메소드에 @abstractmethod 데코레이터를 추가하면 끝이다.

아래 예제를 통해 추상 클래스를 만드는 방법을 단계별로 살펴 보자.

class Shape :
    def Draw(self) :
        pass

class Rect(Shape) :
    pass

s = Shape()
r = Rect()
r.Draw()

Shape라는 기반 클래스를 상속 받아 Rect라는 파생 클래스를 만들고, 파생 클래스 객체를 이용해 Shape 클래스의 Draw() 메소드를 호출하는 코드다.

지금은 위 코드를 실행하면 아무런 문제 없이 실행 된다. 그럼 이제 부터 Shape 클래스를 추상 클래스화 하여 파생 클래스 Rect에서 Draw메소드를 강제로 구현하도록 만들어 보도록 하자.

  • ABC클래스와 abstractmethod를 임포트 한다.
from abc import ABC, abstractmethod
  • Shape 클래스를 ABC 클래스로 부터 상속 받도록 하여 추상 클래스로 정의 한다.
from abc import ABC, abstractmethod

class Shape :
    ...
  • Draw 메소드에 abstractmethod 데코레이터를 적용하여 추상 메소드로 정의 한다.
from abc import ABC, abstractmethod

class Shape :

    @abstractmethod
    def Draw(self) :
        pass

이렇게 Shape 클래스를 수정 후 다시 예제를 실행하면 가장 먼저 Shape 클래스에는 아직 구현이 되어 있지 않은 Draw라는 추상 메소드가 남아 있는 상태이므로 객체를 만드는 것이 불가능 하다는 오류를 만난다.

from abc import ABC, abstractmethod

class Shape(ABC) :

    @abstractmethod
    def Draw(self) :
        pass

class Rect(Shape) :
    pass

s = Shape() # TypeError: Can't instantiate abstract class Shape with abstract method Draw
r = Rect()
r.Draw()

그럼 Shape 클래스 인스턴스화(객체를 만드는 것)를 삭제하고 다시 실행을 시켜 보자.

from abc import ABC, abstractmethod

class Shape(ABC) :

    @abstractmethod
    def Draw(self) :
        pass

class Rect(Shape) :
    pass

# s = Shape()
r = Rect()  # TypeError: Can't instantiate abstract class Rect with abstract method Draw
r.Draw()

이번에는 Rect 클래스에서 동일한 에러가 발생한다. 추상 클래스를 인스턴스화 하기 위해서는 클래스 내부의 추상 메소드들을 모두 재정의 해주어야 한다.

from abc import ABC, abstractmethod

class Shape(ABC) :

    @abstractmethod
    def Draw(self) :
        pass

class Rect(Shape) :

    def Draw(self) :
        print('Draw Rect')

r = Rect()  
r.Draw()     # Draw Rect

Rect 파생 클래스에서 추상 메소드로 정의된 Draw를 재정의하고 코드를 다시 실행하면 정상적으로 실행 되는 것을 확인 할 수 있다.

마치며

이번 장에서는 파이썬에서 제공하는 추상 클래스와 메소드의 사용 문법에 대해 알아 보았다. 요약 하면 

  • from abc import ABC, abstractmethod
  • ABC 클래스 상속
  • @abstractmethod 데코레이터

정도가 되겠다.

위와 같이 클래스에 구현 내용은 없고 뭘 구현해야만 할지 메소드들의 이름만 나열해 놓은 추상 클래스를 인터페이스라고도 부른다. 클래스를 인터페이스로 활용하는 방법은 추후 나오는 디자인 패턴이라던지 각종 프레임워크에서 즐겨 쓰는 방식이므로 주의 깊게 살펴 보도록 하자.

이상 파이썬 클래스에 대한 강좌는 이 정도로 마무리 하도록 하겠다. 부족한 내용에 대한 지적이나 궁금증들은 댓글로 부탁드리며, 다음 포스트에서 파이썬 핵심 기능 중의 하나인 디스크립터(Descriptor)에 대해 알아 보는 시간을 갖도록 하겠다.

부록 1. 같이 보면 좋은 글

유익한 글이었다면 공감(❤) 버튼 꾹!! 추가 문의 사항은 댓글로!!