오늘은 파이썬에서 기본으로 제공하는 자료구조가 어떤
것이 있는지 겉핥기식으로 쭉 고속으로 관광가겠습니다~ 🙂
내장 자료구조
우선 기본 내장자료구조 str, unicode, list, tuple, dict, set 여섯가지에서 아무 기능이나 하나씩 써 봅시다. ^.^;
>>> '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 타입이지만 그래도 그냥 나머지도 끼워줘 봅시다;
>>> 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)
>>> bf = buffer('ARNDCQEGHILKMFPSTWYVBZX', 5, 500)
>>> len(bf), bf[:3] # buffer 타입 (사실은 C 모듈에 붙어야 유용..)
(18, 'QEG')
>>> s = slice(1, 10, 2)
>>> 'ARNDCQEGHILKMFPSTWYVBZX'[s]
'RDQGI'
bool, frozenset 등등은 그냥 넘어갑시다 -ㅇ-;
이제 기본 자료형을 보았으니 다음으로 표준 확장 모듈 자료구조들을..
표준 라이브러리 자료구조
작은 값을 많이 저장할 때 효율적으로 메모리또는 디스크에 들고 있을
수 있는 array
모듈입니다.
>>> 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)로
쓸 수 있게 해줍니다. 스케줄링 루틴 같은 곳에서 정말 편리합니다.
속도가 무진장 빠릅니다. 🙂
>>> 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가 꽤 쓸만합니다.)
>>> 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
입니다.
>>> 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
도 한 번..
>>> 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