매직 매소드란?
클래스 안에 있는 특별한 메소드 이며 대표적인 예로 __init__, __str__ 메소드가 있습니다.
a = 1
b = 2
print(a + b) # 3
그리고, 예를 들어 위 코드처럼 a 와 b 는 각각 1 과 2를 할당한 순간 a, b는 int 클래스의 인스턴스가 되고, int 클래스 내부의 __add__ 매직 메소드에 따라 a+b를 직접적으로 연산할 수 있는 것입니다.
class Practice:
def __init__(self, value):
self._value = value
a = Practice(1)
b = Practice(2)
print(a + b) # TypeError
그러나 이렇게 사용자 정의로 만들어준 클래스에 대해선 __add__ 매직 메소드가 구현되지 않았기 때문에 두 인스턴스에 대해서 곧바로 + 연산자를 사용할 수 없습니다.
class Practice:
def __init__(self, value):
self._value = value
def __add__(self, other):
return self._value + other._value
a = Practice(1)
b = Practice(2)
print(a + b) # 3
만약 이렇게 __add__ 매직 메소드를 추가해 내부 구현을 해주게 된다면 두 인스턴스간에 + 연산을 바로 적용할 수 있게 됩니다.
이와 같이 다른 다양한 종류의 매직 메소드들도 하나하나 살펴보며 구현해보도록 하겠습니다.
__getitem__
__getitem__ 매직 메소드는 리스트나 튜플에 슬라이싱을 적용할 수 있게 하는 메소드 입니다.
class Items:
def __init__(self, *values):
self._values = list(values)
def __getitem__(self, item):
return self._values.__getitem__(item)
c = Items(1, 2, 3, 4, 5, 6, 7)
print(c[:3]) # [1, 2, 3]
__enter__ , __exit__
어떤 파일을 읽을 때, 중간에 예외가 발생하면 그대로 파일을 자동으로 닫아주는 기능을 하는 with문을 적용할 수 있는 매직 메소드 입니다. 만약 파일을 닫아 주지 않는다면 프로그램이 종료되어도 파일은 계속 열려있는 문제가 발생할 수 있기 때문이죠.
f = open("file.txt", "r")
try:
print(f.readlines())
finally:
f.close()
# 같은 내용의 코드 입니다.
with open("file.txt", "r") as f:
print(f.readlines())
__enter__ 매직 메소드는 with문에 진입할 때 자동으로 호출되고, __exit__매직 메소드는 with문을 나올 때 자동으로 호출됩니다.
이 원칙을 이용하여 with문을 자동으로 인식하여 파일을 읽고 닫는 간단한 클래스를 구현해 보겠습니다.
class FileReader:
def __init__(self, file):
self._file = file
def __enter__(self):
self._status = open(self._file, "r")
return self._status
def __exit__(self, type, value, traceback):
self._status.close()
with FileReader("file.txt") as f:
print(f.readlines())
__iter__
__iter__ 매직 메소드는 인스턴스를 반복할 때 호출되는 메소드로 인스턴스를 반복 가능하게 만들어 줍니다.
class NumIter:
def __init__(self, value_1, value_2):
self._start = value_1
self._end = value_2
def __iter__(self):
point = self._start
while point < self._end:
yield point
point += 1
for i in NumIter(1, 10):
print(i, end="") # 123456789
__contains__
__contains__ 매직 메소드는 in 문을 인식해 Boolean 값을 반환하는 메소드 입니다.
class Detector:
def __init__(self, items):
self._items = items
def __contains__(self, item):
return item in self._items
print(3 in Detector(range(1, 10))) # True
__getattr__
__gettattr__은 인스턴스의 특정 속성을 호출할 때, 그 속성이 없으면 대신 호출되는 매직 메소드 입니다.
class Attributer:
def __init__(self, name):
self.name = name
def __getattr__(self, attr):
return attr + " not found"
attr = Attributer("Mike")
print(attr.name) # Mike
print(attr.wrongname) # wrongname not found
__call__
__call__ 매직 메소드는 인스턴스를 일반 함수처럼 호출이 가능하도록 만들어 줍니다.
아래 코드는 __call__을 이용해 특정 값으로 인스턴스가 몇 번 호출되었는지 리턴하는 클래스를 구현한 것입니다.
class Counter:
def __init__(self):
self._count = {}
def __call__(self, value):
try:
self._count[value] += 1
except KeyError:
self._count[value] = 1
return self._count[value]
counter = Counter()
print(counter(1)) # 1
print(counter(2)) # 1
print(counter(1)) # 2
참고 자료
- <파이썬 클린 코드 : 유지보수가 쉬운 파이썬 코드를 만드는 비결, 마리아노 아나야 지음>
- 파이썬의 컨텍스트 매니저 (Context Manager) 에 대해 알아봅시다. - https://sjquant.tistory.com/12
'프로그래밍 언어 > Python' 카테고리의 다른 글
[Python] 제너레이터 (0) | 2021.11.11 |
---|---|
[Python] 유용한 데이터 구조 (0) | 2021.11.07 |
[Python] 파이썬 다운 코딩 (0) | 2021.11.05 |
[Python] SOLID 원칙 (0) | 2021.10.03 |
[Python] 파이썬 프로그래밍의 개발 지침 (0) | 2021.10.01 |