본문 바로가기
python

파이썬 기초 - 메타 클래스와 추상 클래스

by kyeongseo.oh 2025. 3. 23.

추상 클래스 (Abstract Class)

추상 클래스는 하나 이상의 추상 메서드를 가지고, 직접 인스턴스화할 수 없는 클래스이다. 서브클래스에서 반드시 구현해야 하는 메서드를 정의할 때 사용하며, abc 모듈을 사용해 선언한다. 

추상 클래스는 서브클래스에서 특정 메서드를 반드시 구현해야 할 때 사용한다. 또한 추상 클래스를 사용하면 일관된 인터페이스를 제공할 수 있다.

from abc import ABC, abstractmethod

class Animal(ABC):
    def eat(self):
        return "냠냠 쩝쩝"
    
    @abstractmethod
    def make_sound(self):
        """서브 클래스에서 반드시 구현해야 하는 메서드"""
        pass

# 서브클래스에서 반드시 `make_sound` 구현해야 함.
class Dog(Animal):
    def make_sound(self):
        return "멍멍!"

class Cat(Animal):
    def make_sound(self):
        return "야옹!"
    
class Bird(Animal):
    pass

dog = Dog()
cat = Cat()
# bird = Bird() # TypeError: Can't instantiate abstract class Bird with abstract method make_sound

# animal = Animal()  # TypeError: 인스턴스 생성 불가

 

위 예제에서 Bird는 make_sound 메서드를 구현하지 않아, 객체 선언 시 에러가 발생한다.

메타클래스 (Metaclass)

보통의 클래스가 객체를 만든다면, 메타클래스는 클래스 자체를 만들고 수정한다. 메타 클래스를 사용하면 클래스의 생성, 동작, 구조를 제어할 수 있다. 파이썬에서  type은 클래스 자체를 만드는 메타클래스로, 모든 클래스는 기본적으로 type의 인스턴스다.

 

보통 우리는 아래와 같이 클래스를 만들어서 객체를 생성한다. 이때 p는 Person의 인스턴스이며, Person은 type의 인스턴스이다.

class Person:
    pass

p = Person()  # Person 클래스의 인스턴스 생성
print(type(p))  # 출력: <class '__main__.Person'>
print(type(Person))  # 출력: <class 'type'>

type을 사용하여 클래스 만들기

type을 사용하면 class 키워드를 사용하지 않아도 클래스를 만들 수 있다.

기본 구문

type('MyClass', (BaseClass,), {'attribute': value, 'method': function})

 

type(이름, 부모 클래스, 속성)을 사용하면 클래스를 동적으로 생성할 수 있다. 하지만 type을 직접 사용하기보다는 메타클래스를 만들어서 활용하는 것이 일반적이다.

def greet(self):
    return f"안녕하세요, {self.name}입니다"

MyClass = type('MyClass', (), {'name': "홍길동", 'greet': greet})
my = MyClass()
print(my.greet()) # 안녕하세요, 홍길동입니다

메타클래스 직접 만들기

메타클래스의 __new__ 메서드는 cls, name, bases, attrs 매개변수들을 사용하여 클래스 생성 과정을 제어한다.

class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        if "name" not in attrs:
            raise TypeError("클래스에 'name' 속성이 있어야 합니다.")
        return super().__new__(cls, name, bases, attrs)

# 올바른 클래스
class Person(metaclass=MyMeta):
    name = "홍길동"

# 잘못된 클래스 (name 속성이 없음)
class InvalidClass(metaclass=MyMeta):
    pass  # TTypeError: 클래스에 'name' 속성이 있어야 합니다.

 

  • cls:
    • 현재 메타클래스(여기서는 MyMeta)를 가리킨다.
    • 일반 클래스의 메서드에서 self와 비슷한 개념
  • name:
    • 생성하려는 클래스의 이름
    • 예제에서는 "Person" 또는 "InvalidClass"
  • bases:
    • 생성하려는 클래스가 상속받는 부모 클래스들의 튜플
  • attrs:
    • 생성하려는 클래스의 속성과 메서드를 담은 딕셔너리
    • Person 클래스의 경우 {'name': '홍길동'}이 포함된다.
    • InvalidClass의 경우 name 속성이 없어 오류가 발생한다.

 

댓글