__repr__ vs __str__: 객체를 문자열로

Python __repr__과 __str__의 차이, 각각의 사용처, f-string 포맷 지정자, __format__ 구현법을 설명합니다.

· 4 min read · PALDYN Team

지난 글에서 Python 매직 메서드의 전체 카테고리를 살펴보았습니다. 그 중 __repr____str__은 가장 자주 구현하는 메서드입니다. 이 두 메서드를 혼동하거나 둘 중 하나만 구현하면 디버깅이 어려워지거나 출력이 이상해집니다.

기본 원칙

  • __repr__: 개발자용. 객체를 재현(reproduce) 할 수 있는 문자열. REPL, 로깅, 디버깅에 사용
  • __str__: 사용자용. 읽기 좋은 형태의 문자열. print(), f-string 기본값에 사용

중요한 규칙 두 가지:

  1. __repr__만 구현하면 str()__repr__을 사용한다 → 최소한 __repr__은 항상 구현하라
  2. __str__만 구현하면 repr()object.__repr__의 기본값(<Money object at 0x...>)을 사용한다

호출 경로

repr() vs str() 호출 흐름

기본 구현

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __repr__(self):
        # eval(repr(p)) == p 가 이상적
        return f"Point({self.x!r}, {self.y!r})"

    def __str__(self):
        return f"({self.x}, {self.y})"

p = Point(3, 4)
print(repr(p))   # Point(3, 4)
print(str(p))    # (3, 4)
print(p)         # (3, 4) — print는 str() 사용

# REPL에서 식 평가
p  # Point(3, 4) 출력 — repr 사용

!r 변환 플래그는 f-string 안에서 repr()을 호출합니다. 문자열 속성이 있으면 따옴표가 함께 출력되어 재현 가능성이 높아집니다.

repr 재현 가능성 원칙

이상적인 __repr__eval(repr(obj))으로 동일한 객체를 재생성할 수 있어야 합니다.

from datetime import date
d = date(2026, 5, 16)
print(repr(d))         # datetime.date(2026, 5, 16)
eval("__import__('datetime').date(2026, 5, 16)")  # date(2026, 5, 16)

항상 가능하지 않더라도, 적어도 타입과 핵심 상태를 보여주는 형태가 좋습니다.

class Connection:
    def __init__(self, host, port):
        self.host, self.port = host, port

    def __repr__(self):
        return f"Connection(host={self.host!r}, port={self.port!r})"

__repr__과 str 구현 패턴

format: f-string 포맷 명세어 지원

f"{obj:.2f}" 형태로 포맷 명세어를 전달하면 obj.__format__(".2f")가 호출됩니다.

class Temperature:
    def __init__(self, celsius):
        self.celsius = celsius

    def __repr__(self):
        return f"Temperature({self.celsius!r})"

    def __format__(self, spec):
        if spec == "F":
            return f"{self.celsius * 9/5 + 32:.1f}°F"
        if spec == "K":
            return f"{self.celsius + 273.15:.2f}K"
        return f"{self.celsius:.1f}°C"

t = Temperature(100)
print(f"{t}")    # 100.0°C
print(f"{t:F}")  # 212.0°F
print(f"{t:K}")  # 373.15K

dataclass의 repr

@dataclass__repr__을 자동 생성합니다. 수동으로 구현할 필요가 없어 보일 때 유용합니다.

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float

p = Point(1.0, 2.0)
print(repr(p))  # Point(x=1.0, y=2.0)

repr=False를 전달하면 자동 생성을 끌 수 있습니다.

컨테이너 내부 객체 표현

리스트나 딕셔너리에 담긴 객체는 __repr__을 사용합니다.

class Dog:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return f"Dog({self.name!r})"
    def __str__(self):
        return self.name

dogs = [Dog("Rex"), Dog("Max")]
print(dogs)        # [Dog('Rex'), Dog('Max')] — __repr__ 사용
print(dogs[0])     # Rex — __str__ 사용

지난 글: 매직 메서드(Special Methods) 개요

다음 글: __eq__와 hash


읽어주셔서 감사합니다. 😊