본문 바로가기

Python study

Python Special method (magic method)

Python에서 특별 메소드를 마술 메소드(magic method)라고 한다.

<(__메소드__ 로 이루어진 메소드 의미) __로 시작되어 던더 메서드라고도 한다.>

특별 메소드 대해 설명해 보고자 한다.

__getitem__(), __len__() 예시

class MyList:
    def __init__(self, items):
        self._items = items

    # 클래스의 인스턴스에서 [] 연산자를 사용할 때 호출
    def __getitem__(self, index):
        return self._items[index]

    # 클래스의 인스턴스에 대해 len() 함수가 호출될 때 사용
    def __len__(self):
        return len(self._items)


# MyList 클래스의 인스턴스 생성
my_list = MyList([1, 2, 3, 4, 5])

# __getitem__ 메소드를 통해 특정 인덱스의 아이템 접근
print(my_list[2])  # 출력: 3

# __len__ 메소드를 통해 리스트의 길이 구하기
print(len(my_list))  # 출력: 5

해당 __getitem__() 경우에는 인덱스를 접근하는 ramdom.choice, 슬라이싱, reversed(), sorted() 에도 적용이 가능하다.

import random


class MyList:
    def __init__(self, items):
        self._items = items

    def __getitem__(self, index):
        return self._items[index]

    def __len__(self):
        return len(self._items)


# MyList 클래스의 인스턴스 생성
my_list = MyList([1, 2, 3, 4, 5])

# random.choice() 예시
print(random.choice(my_list))  # my_list 중 랜덤한 아이템 반환

# 슬라이싱 예시
sliced_list = my_list[1:4]
print(sliced_list)  # 출력: [2, 3, 4]

# reversed() 예시
for item in reversed(my_list):
    print(item, end=' ')  # 출력: 5 4 3 2 1

print()  # 줄바꿈

# sorted() 예시 - 역순으로 정렬
new_list = MyList([3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5])
sorted_list = sorted(new_list, reverse=True)
print(sorted_list)  # 출력: [9, 6, 5, 5, 5, 4, 3, 3, 2, 1, 1]

random.shuffle() 함수는 리스트와 같은 가변 시퀀스를 무작위로 섞는다. 그러나 이 함수는 인자로 전달된 시퀀스를 직접 변경하기 때문에, 불변 객체에는 사용할 수 없다.

구현된 MyList 클래스의 경우, 내부에서 리스트(list)를 사용하여 아이템을 관리한다. 따라서, MyList 인스턴스의 내부 상태는 가변적이므로, 이론상으로는 셔플링이 가능하다. 하지만, random.shuffle() 함수를 직접 MyList 인스턴스에 사용하려면, MyList 클래스가 적절한 인터페이스를 제공해야 한다. 즉, MyList 객체를 random.shuffle()에 사용하기 위해서는 MyList가 가변 시퀀스로 작동할 수 있도록 __setitem__ 메소드를 구현해야 한다. (추후 업로드 예정)

__repr__을 통해 객체의 문자열 표현을 제공하고, __abs__, __add__, **__mul__**을 통해 절대값 계산, 덧셈, 곱셈 연산을 지원할 수 있다.

class CustomNumber:
    def __init__(self, value):
        self.value = value

    # 객체의 문자열 표현
    def __repr__(self):
        return f"CustomNumber({self.value})"

    # 덧셈 연산
    def __add__(self, other):
        return CustomNumber(self.value + other.value)

    # 곱셈 연산
    def __mul__(self, other):
        return CustomNumber(self.value * other.value)


# CustomNumber 인스턴스 생성 및 연산 예시
num1 = CustomNumber(5)
num2 = CustomNumber(3)

# 덧셈 연산
print(num1 + num2)  # CustomNumber(8)

# 곱셈 연산
print(num1 * num2)  # CustomNumber(15)

repr vs str

__repr__

  • __repr__ 메소드는 객체의 “공식적인” 문자열 표현을 제공한다.
  • 개발자가 객체를 인식하고, 디버깅할 때 유용하게 사용된다.
  • 이 메소드의 목적은, 가능하다면, eval() 함수를 사용하여 해당 문자열로부터 같은 객체를 다시 생성할 수 있는 유효한 Python 표현식을 반환하는 것이다.
  • Python 인터프리터에서 객체를 입력하면 기본적으로 __repr__의 결과가 출력된다.
  • 클래스에 __str__ 메소드가 정의되어 있지 않은 경우, __repr__의 결과가 print() 함수 호출 시 사용된다.

__str__

  • __str__ 메소드는 객체를 “비공식적으로”, 더 읽기 쉬운 형태로 문자열로 표현하기 위해 사용한다.
  • 주로 최종 사용자에게 보여주기 위한 목적으로 설계되었다.
  • print() 함수나 str() 내장 함수가 호출될 때 이 메소드가 사용된다.
  • 클래스에서 이 메소드를 구현하지 않으면, Python은 대신 __repr__ 메소드의 결과를 사용한다.
class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    def __repr__(self):
        return f"Date({self.year}, {self.month}, {self.day})"

    def __str__(self):
        return f"{self.year}-{self.month}-{self.day}"

d = Date(2020, 1, 5)
print(repr(d))  # Date(2020, 1, 5)
print(str(d))   # 2020-1-5
print(d)        # __str__ 메소드의 결과인 '2020-1-5' 출력, __str__이 없으면 __repr__의 결과 출력

 

파이썬 언어 참조문서 데이터 모델장 부분에 메소드들이 정리되어있다.

https://docs.python.org/3.12/reference/datamodel.html

 

3. Data model

Objects, values and types: Objects are Python’s abstraction for data. All data in a Python program is represented by objects or by relations between objects. (In a sense, and in conformance to Von ...

docs.python.org

 

모든 코드는 github에 저장되어 있습니다.

https://github.com/SeongUk18/python

728x90