Python 기본 자료형의 확장
※ 이 글은 원본이 갱신되었습니다. 원본을 읽어주시면 감사하겠습니다.
이상한모임 Python 채널에서 이런 질문이 왔었다.
파이썬에서 dict 기본적으로 [key] 로 접근하는데 .key 로 접근하도록 변환하는 방법이 있을까요?
사실 이 질문의 답은 AttrDict라는 구현체가 있으므로 가져다 쓰는 것이다.
하지만 직접 만드는 것도 전혀 어렵지 않기 때문에 간단히 구현해보고자 한다.
Python에서 a라는 object에 대해서 a['key']와 같은 방식으로 ['key']를 사용하면 내부적으로는 a.__getitem__('key')과 같이 처리된다.
a.key와 같은 방법으로 사용하면 내부적으로는 a.__getattr__('key')과 같이 처리된다.
즉, __***attr__이 호출되면 __***item__이 반환되게 하면 이 문제는 해결된다.
왜 ***이라고 적었느냐 하면, get외에도 set과 del이 있기 때문이다.1
간단하게 구현해보면 다음과 같다.
class AttrDict(dict):
def __getattr__(self, attr):
return self.__getitem__(attr)
def __setattr__(self, attr, value):
return self.__setitem__(attr, value)
def __delattr__(self, attr):
return self.__delitem__(attr)
실제로 테스트도 해보았다.
>>> from attrdict import AttrDict
>>> a = AttrDict()
>>> a['a'] = 1
>>> a.a
1
>>> a.a = 3
>>> a.a
3
>>> del a.a
>>> a['a']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'a'
위에 적었던 소스를 보면 알 수 있지만, 기본 자료형, 예를 들면 위에서 쓰인 dict등의 자료형은 그 자체로 이미 class이기때문에 상속받아서 활용하는 것이 가능하다.
예를 들면 다음과 같은 소스를 보자.2
class BookList(object):
list = []
def add_book(self, title, author):
self.list.append((title, author))
책 목록을 관리하는 class라고 만든 것인데, 개발 자체는 쉬울지 몰라도 실제로 활용하려고 하면 아래와 같은 문제들이 있을 것이다.
>>> book_list = BookList()
>>> book_list.add_book('훈민정음', '세종대왕')
>>> book_list
????
????로 해놓았는데, 당연히 저 결과는 instance이다.
즉, 실행할때마다 다른 값이 나올것이고, 우리가 원하는 book_list에 있는 실제 책 목록을 볼 수 없다.
물론 book_list.list라고 하면 되겠지만 book_list라고 하면 나오면 될 문제인데 뭔가 많이 돌아가는 느낌이다.
여기서 쓴 방법 대신 list 자료형을 상속받으면 다음과 같이 쓸 수 있다.
class BookList(list):
def add_book(self, title, author):
self.append((title, author))
이렇게 활용하면 장점이 몇 가지 있는데 꼽아보자면 다음과 같다.
- 정적 분석기가 자료형을 보다 잘 인식할 수 있다.
- 이미 기본으로 제공되는 메소드를 그대로 가져다 쓸 수 있다.
- type명만 보고도 그 동작을 알 수 있으므로 사용성이 증가된다.
- 1과 2로 인해 불필요한 라인 수와 중복, 그리고 버그를 줄일 수 있다.
물론 상속이 만능은 아니다.
보다 복잡한 자료 구조가 필요하다면 직접 만들어야하는 경우도 존재할 것이다.
하지만 간단하게 끝낼 수 있는 경우임에도 불구하고 복잡한 자료형을 만드는 것은 낭비 아닐까 생각해본다.