오늘은 파이썬에서 기본으로 제공하는 자료구조가 어떤
것이 있는지 겉핥기식으로 쭉 고속으로 관광가겠습니다~ 🙂
내장 자료구조
우선 기본 내장자료구조 str, unicode, list, tuple, dict, set 여섯가지에서 아무 기능이나 하나씩 써 봅시다. ^.^;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
>>> '6,7-dihydro-1-methyl-7-oxo-3-propyl'.partition('-') ('6,7', '-', 'dihydro-1-methyl-7-oxo-3-propyl') >>> u'def\ttest()'.expandtabs() # unicode 타입 u'def test()' >>> l = [1, 2, 3, 4] # list 타입 >>> l.sort(key=lambda v: - v**2 % 5) >>> l [2, 3, 1, 4] >>> t = 3, 4 # tuple 타입 >>> t * 5 (3, 4, 3, 4, 3, 4, 3, 4, 3, 4) >>> d = dict.fromkeys('12345') >>> d.update({'4': 1, '6': 2}) >>> d {'1': None, '3': None, '2': None, '5': None, '4': 1, '6': 2} >>> set('TOMMARVOLORIDDLE') - set('IAMLORDVOLDEMORT') set([]) |
밑의 타입들은 보통 다른 언어에서는 자료구조라기보다는 그냥 primitive 타입이지만 그래도 그냥 나머지도 끼워줘 봅시다;
1 2 3 4 5 6 7 8 |
>>> map((5).__mul__, range(3)) # int/long 타입 [0, 5, 10] >>> (1+5j)**2 # complex 타입 (-24+10j) >>> divmod(5.3, 3.1) # float 타입 (1.0, 2.1999999999999997) |
1 2 3 4 5 6 7 8 |
>>> bf = buffer('ARNDCQEGHILKMFPSTWYVBZX', 5, 500) >>> len(bf), bf[:3] # buffer 타입 (사실은 C 모듈에 붙어야 유용..) (18, 'QEG') >>> s = slice(1, 10, 2) >>> 'ARNDCQEGHILKMFPSTWYVBZX'[s] 'RDQGI' |
bool, frozenset 등등은 그냥 넘어갑시다 -ㅇ-;
이제 기본 자료형을 보았으니 다음으로 표준 확장 모듈 자료구조들을..
표준 라이브러리 자료구조
작은 값을 많이 저장할 때 효율적으로 메모리또는 디스크에 들고 있을
수 있는 array
모듈입니다.
1 2 3 4 5 6 7 8 9 10 |
>>> import array >>> arr = array.array('h') >>> arr.append(123) >>> arr.extend([34,5,8]) >>> arr.tostring() '{\x00"\x00\x05\x00\x08\x00' >>> arr.tofile(open('myarr', 'w')) >>> arr.pop() 8 |
heapq
모듈은 기본 list자료형을 가지고 우선순위 큐(priority queue)로
쓸 수 있게 해줍니다. 스케줄링 루틴 같은 곳에서 정말 편리합니다.
속도가 무진장 빠릅니다. 🙂
1 2 3 4 5 6 7 8 9 10 |
>>> import heapq >>> l = list(['ham', 'egg', 'spam', 'britney', 'guido']) >>> heapq.heapify(l) >>> heapq.nlargest(1, l) ['spam'] >>> heapq.nsmallest(2, l) ['britney', 'egg'] >>> map(heapq.heappop, [l]*5) ['britney', 'egg', 'guido', 'ham', 'spam'] |
bisect
모듈은 정렬된 list에서 이진검색법으로 자료의 위치를 찾아줍니다.
dict로 다루기에는 자료의 양이 많거나, 순서가 중요한 경우에 쓸만합니다.
아래 예제는 동전을 몇 번 던지면 앞면이 나오나 같은 경우를 나타내는
기하분포 랜덤함수를 bisect로 만든 방법인데, 그냥 계산해버리는
방법도 있지면 예제를 위해서 –; (실제로 분포함수가 없고 그냥 이산확률만
덩그러니 주어졌을 때 bisect가 꽤 쓸만합니다.)
1 2 3 4 5 6 7 8 9 |
>>> import bisect, random >>> geometric_cdf = lambda p, k: 1 - (1 - p)**k >>> cumprob = map(geometric_cdf, [0.5] * 20, range(20)) >>> cumprob[:10] [0.0, 0.5, 0.75, 0.875, 0.9375, 0.96875, 0.984375, 0.9921875, 0.99609375, 0.998046875] >>> georand = lambda: bisect.bisect_left(cumprob, random.random()) >>> [georand() for i in range(15)] [1, 1, 1, 4, 2, 1, 2, 1, 1, 1, 2, 2, 2, 1, 1] |
다음은 어정쩡한 이름을 달고 있는
collections
입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
>>> import collections >>> counter = collections.defaultdict(lambda: 0) >>> for c in 'wii tennis': ... counter[c] += 1 ... >>> counter.items() [(' ', 1), ('e', 1), ('i', 3), ('n', 2), ('s', 1), ('t', 1), ('w', 1)] >>> dq = collections.deque() >>> dq.append(1); dq.append(2) >>> dq.appendleft(3) >>> dq deque([3, 1, 2]) >>> dq.pop() 2 >>> dq.popleft() 3 >>> dq deque([1]) |
빼놓으면 서운하니까
bsddb
도 한 번..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
>>> import bsddb >>> hdb = bsddb.hashopen('test', 'c') >>> hdb['byam'] = 'uhung`' >>> hdb.keys() ['byam'] >>> del hdb['byam'] >>> hdb.close() >>> rndb = bsddb.rnopen('test2', 'c') >>> rndb[1] = 'sujiniya' >>> rndb[3] = 'geosigi' >>> rndb.items() [(1, 'sujiniya'), (3, 'geosigi')] >>> rndb[2] = 'wae?' >>> rndb.items() [(1, 'sujiniya'), (2, 'wae?'), (3, 'geosigi')] >>> # B+Tree는 너무 똑같은 것 계속하면 지루해서 생략 -ㅇ-; |
이 외에도
UserString,
UserDict,
StringIO,
decimal,
Queue
등 유용한 것이 많이 있습니다만, 신비감 조성을 위해서 모두 소개하지 않고
이쯤에서 마칩니다. =3=33
일 년 전에 이 글이 있었다면 얼마나 좋았을까요. ㅠ.ㅠ; 몸으로 부딧히며 생짜로 구현했다가 더 좋은게 기본적으로 있다는걸 알고 좌절하기 수십번-_-
슬플 뿐입니다. ㅎㅎ
파이썬 관광모듈 아주 흥미롭게 보고 있습니다. 이번회는 제게 아주 유용해서 좋은 글 감사드립니다. Python이 computational science에 강하다(?)는 얘길 여기저기서 듣고, 무척이나 관심있게 보고 있습니다.
Python를 computational science(optimization-linear/integer/dynamic programming, simulation)에서 효과적으로 쓰기 위한 tool (IDE, editor, debugger, popular APIs) 들도 한번 소개해주심 너무 좋겠습니다.