공부 정리
매직 메서드
jjnll
2025. 1. 29. 18:38
매직 메서드(던더 매서드)가 익숙하지 않아서 따로 정리한다.
몰랐을 때는 쓰면서도 굳이 언더바를 추가해서 보낼 필요가 있나 하는 생각이 마음 한켠에 항상 있었는데, 퍼플에 물어보니 매직 메서드를 쓰지 않으면 리턴값에 해당 연산자 혹은 매서드를 쓸 수 없다고 한다. 파이썬은 자바스크립트나 욜로 모델과는 다르게 데이터로더, 토치라이트닝에서 쓰듯이 미리 지정해 주어야 사용이 가능하다.
class CustomList:
def __init__(self, name, items):
"""객체 초기화"""
self.name = name
self.items = items # 리스트 형태의 데이터
def __str__(self):
"""객체의 사용자 친화적인 문자열 표현"""
return f"CustomList(name={self.name}, items={self.items})"
def __repr__(self):
"""객체의 공식적인 문자열 표현 (디버깅용)"""
return f"CustomList({repr(self.name)}, {repr(self.items)})"
def __len__(self):
"""객체의 길이를 반환 (items의 길이)"""
return len(self.items)
def __getitem__(self, index):
"""인덱싱 가능하게 구현"""
return self.items[index]
def __setitem__(self, index, value):
"""인덱스에 값 할당 가능하게 구현"""
self.items[index] = value
def __iter__(self):
"""이터레이터 반환"""
return iter(self.items)
def __next__(self):
"""다음 이터레이터 값 반환 (예: next())"""
if not hasattr(self, "_iter"):
self._iter = iter(self.items)
return next(self._iter)
def __add__(self, other):
"""덧셈 연산 (+ 연산자)"""
if isinstance(other, CustomList):
combined_name = f"{self.name} + {other.name}"
combined_items = self.items + other.items
return CustomList(combined_name, combined_items)
return NotImplemented
def __call__(self, *args, **kwargs):
"""객체를 함수처럼 호출 가능하게 구현"""
print(f"{self.name} was called with args={args} and kwargs={kwargs}")
def __del__(self):
"""객체 소멸 시 호출"""
print(f"CustomList '{self.name}' is being deleted.")
# 사용 예제
if __name__ == "__main__":
# 객체 생성
clist1 = CustomList("List1", [1, 2, 3])
clist2 = CustomList("List2", [4, 5])
# __str__ 및 __repr__
print(str(clist1)) # 출력: CustomList(name=List1, items=[1, 2, 3])
print(repr(clist2)) # 출력: CustomList('List2', [4, 5])
# __len__
print(len(clist1)) # 출력: 3
# __getitem__, __setitem__
print(clist1[0]) # 출력: 1
clist1[0] = 10
print(clist1[0]) # 출력: 10
# __iter__, __next__
for item in clist1:
print(item) # 출력: 10, 2, 3
# __add__
clist3 = clist1 + clist2
print(clist3) # 출력: CustomList(name=List1 + List2, items=[10, 2, 3, 4, 5])
# __call__
clist1(42, key="value")
# 출력: List1 was called with args=(42,) and kwargs={'key': 'value'}
# 객체 소멸 (__del__)
del clist1
# eq, lt
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def __eq__(self, other):
return self.width * self.height == other.width * other.height
def __lt__(self, other):
return self.width * self.height < other.width * other.height
r1 = Rectangle(3, 4)
r2 = Rectangle(6, 2)
print(r1 == r2) # 출력: True (넓이가 같음)
print(r1 < r2) # 출력: False
## print의 각 연산자들과 클래스 내부의 정의와 연결.
## 클래스를 정의해서 들어온 뒤, 클래스 내부에서 연산자와 함수와 연결.
# enter, exit for file control
class FileManager:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
# 파일 열기
self.file = open(self.filename, 'w')
return self.file
def __exit__(self, exc_type, exc_value, traceback):
# 항상 파일을 닫아 리소스를 해제
self.file.close()
# 사용 예시
with FileManager('test.txt') as f:
f.write('Hello World!')
## 파일을 열고, 라인을 입력한 뒤, 저장 후, 닫는 단계 진행.
728x90