<aside> 💡 매직 메소드는 __init__() 과 같이 두 개의 언더스코어로 둘러싸인 메소드들로, 인스턴스의 기본적인 기능들을 정의하는데 사용되는 특별한 메소드들입니다.

</aside>

메소드 기능 설명
__init__(self, ...) 객체 초기화 생성자에 해당
__str__(self) 비공식적 문자열 표현 str() 함수 호출 시 사용, 사용자가 보기 편한 형태로 표현
__repr__(self) 공식적 문자열 표현 디버깅과 로깅 목적으로 사용, eval로 다시 객체를 복구할 수 있는 형태 권장
__call__(self, ...) 객체 호출 가능 객체를 함수처럼 호출할 수 있게 함
__add__(self, other) 덧셈 연산 self + other 구현, 덧셈 연산자 오버로딩
__sub__(self, other) 뺄셈 연산 self - other 구현, 뺄셈 연산자 오버로딩
__mul__(self, other) 곱셈 연산 self * other 구현, 곱셈 연산자 오버로딩
__neg__(self) 단항 음수 객체에 - 연산자를 사용할 때의 동작을 정의
__pos__(self) 단항 양수 객체에 + 연산자를 사용할 때 (일반적으로는 기본 동작과 동일)
__len__(self) 길이 반환 len() 함수 호출 시 객체의 길이 반환
__contains__(self, item) 멤버십 테스트 in 연산자 사용 시 항목이 객체에 속해 있는지 확인

__str__(self) / __repr__(self)

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 개발자가 보기 위한 기술적 표현
    def __repr__(self):
        return f'Person({self.name!r}, {self.age})'

    # 사용자가 보기 위한 쉬운 문자열 표현
    def __str__(self):
        return f'{self.name}씨는 {self.age} 살입니다.'

# 💡 디버깅시 어느 쪽이 나오는지 확인
person = Person('김돌준', 30)

person_repr = (repr(person))

person_str = str(person)

# 💡 프린트시 어느 쪽이 나오는지 확인
print(person)

pass

__call__(self, ...)

class Soldier:
    def __init__(self, rank, name):
        self.rank = rank
        self.name = name

    def __call__(self):
        print(f"{self.rank} {self.name}!")

soldier_1 = Soldier("이병", "김돌준")
soldier_2 = Soldier("상병", "유린기")

soldier_1()
soldier_2()

산술연산자들

class Army:
    def __init__(self, generals, infantry, calvary):
        self.generals = generals
        self.infantry = infantry
        self.calvary = calvary

    def __add__(self, other):
        return Army(
            [self.generals[0], other.generals[0]],
            self.infantry + other.infantry,
            self.calvary + other.calvary
        )

    # 기병은 보병 3명 무력으로 가정
    def __eq__(self, other):
        return (self.infantry + (self.calvary * 3)) == (other.infantry + (other.calvary * 3))

    def __lt__(self, other):
        return (self.infantry + (self.calvary * 3)) < (other.infantry + (other.calvary * 3))

    def __gt__(self, other):
        return not (self == other or self < other)

army_1 = Army(["관우", "장비"], 500, 300)
army_2 = Army(["하후돈", "장료"], 800, 400)
army_3 = Army(["태사자", "황개"], 700, 200)

army_4 = army_1 + army_2
# 연속 계산도 가능
army_5 = army_1 + army_2 + army_3

army_1_lt_army_3 = army_1 < army_3
army_1_gt_army_3 = army_1 > army_3

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

    def __neg__(self):
        return Point(-self.x, -self.y)

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

# Point 객체 생성
p = Point(3, -5)

# 단항 음수 연산 적용
neg_p = -p

pass

__len__(self)

class StickSet:
    def __init__(self, number, length):
        self.number = number
        self.length = length

    def __len__(self):
        return self.number * self.length

ss_1 = StickSet(50, 3)
ss_2 = StickSet(35, 6)

ss_1_len = len(ss_1)
ss_2_len = len(ss_2)

pass