시퀀스
시퀀스는 순서가 있는 자료구조를 의미한다.
이 장에서는 표준 라이브러리에서 다루는 시퀸스, 즉 내장 시퀀스 중 일부[리스트, 튜플, 배열, 큐]에 대해 다룬다.
분류
시퀀스는 다음으로 분류할 수 있다.
컨테이너 시퀀스 | 균일 시퀀스 | |
---|---|---|
의미 | 여러 자료형을 담을 수 있는 시퀀스 | 하나의 자료형만 담을 수 있는 시퀀스 |
예 | list, tuple, collections, deque | str, bytes, bytearray, memoryview, array.array |
가변 시퀀스 | 불변 시퀀스 | |
---|---|---|
의미 | 엘리먼트 대입 가능 | 엘리먼트 대입 불가(생성후 고정) |
예 | list, bytearray, array.array, collections, deque, memoryview | tuple, str, bytes |
지능형 리스트와 제너레이터 표현식
1 |
|
대부분의 사람이 알겠지만, 이는 다음과 같다
1 |
|
이를 Comprehension이라 하는데, 리스트를 만드므로 List Comprehension(LC)이라 부른다. 이를 똑같이 Set, Dict에 적용할 수 있는데, 이때는 SC, DC라 부른다.
위 아래를 비교해보면 알겠지만 훨신 간결하고 읽기 좋음을 알 수 있다. 하지만 세 줄이상인 경우, 코드를 분할하거나 for문을 사용하자.
반복문을 두개 이상 둘 수 있다. 다음 예를 보자.
1 |
|
1 |
|
- 파이썬에서 [], {}, ()안에서의 개행은 무시된다.
튜플
튜플은 불변 리스트이다. 하지만 불변 리스트의 위치별로 뭘 저장할지를 정해두면 레코드로서 작용한다.
예
1 |
|
여기서 이상한점이 보인다. city_population는 레코드(도시명, 인구수)인 튜플이다.
"%3s: %5d명" % city_population
는 어떻게 작용하는걸까? 반복형 언패킹에 대해 알아보자.
병렬 할당과 시퀀스 언패킹
시퀀스 언패킹은 시퀀스가 풀리는걸 의미하는데, 다음을 보자.
1 |
|
는 다음과 같다
1 |
|
대입연산(=) 의 왼쪽에 콤마로 구분된 변수들이 나오면(‘()’나 ‘[]’로 묶을 수 있다) 오른쪽의 시퀀스를 풀어 순서대로 대입한다. 이때 콤마로 구분한 것을 왼쪽에 두는 것을 병렬 할당이라 부르고, t가 저렇게 풀리는것을 시퀀스 언패킹이라 한다.
1 |
|
이때 풀리는 객체에 따라 리스트 언패킹, 튜플 언패킹이라 부른다.
1 |
|
위 코드처럼 필요없는 항목에 대해서는 _를 더미처럼 사용하면 된다.
이 코드는 입력의 개수에 따라 오류가 나타난다.
만약 입력이 4개 들어오면?
1 |
|
개수가 정해지지 않았을때는 *를 사용하여 초과한 항목을 잡을 수 있다.
1 |
|
- *l 대신 *_로 버릴 수 있다.
- *a는 객체에 하나만 있어야 한다. (모호해지기 때문)
- 객체를 중첩하여 대입할 수 있다.
명명된 튜플
처음으로 돌아가 city_population예제를 보면 분명 튜플은 레코드의 역할을 할 수 있다. 그러나 각 값에 대한 레이블이 없는 것은 여전히 부족하다.
namedtuple이라는 레이블을 넣을 수 있는 튜플이 더 적합하다.
1 |
|
정형화하면 다음과 같다.
1 |
|
namedtuple은 기존의 t[idx]
를 통해서도 접근할 수 있고, t.attrname
을 통해서도 할 수 있다.
1 |
|
다차원 슬라이싱
1 |
|
NumPy와 같은 외부 패키지에서 2차원 슬라이스를 가져올때 사용한다. 이는 인덱스를 튜플로 받는다. a.__getitem__((i,j))
이때 i나 j 대신 slice로 1::3등을 넣을 수 있다.
또, 나머지 차원을 생략하는 경우, ‘…‘이라는 Ellipsis객체를 보낸다. 예를 들어, x[i,...]
는 x[i,:,:,:]
와 동일하다.
슬라이스에 연산하기
1 |
|
부분에 대한 할당을 할 수 있다.
병렬할당과는 엄연히 다른 문법이다. 슬라이스는 반드시 슬라이싱([::])이 들어가야하며 이는 값으로 평가되는것이 아니다.
1 |
|
대입(=) 왼쪽의 [::]는 연산이 아님을 기억하자.
시퀀스 곱, 덧셈
1 |
|
sort와 sorted
일반적으로 사본을 만들지 않고 시퀀스를 변경하는 함수는 반환값이 None
이다. 새 시퀀스를 생성하지 않았다는 의미.
list.sort()
는 내부의 자료를 정렬하므로,None
을 반환한다.list.sorted()
는 사본을 만들어 정렬한 후 반환한다.- sort, sorted 모두 팀 정렬을 이용한다.
정렬된 시퀀스를 bisect로 관리하기
bisect 모듈은 bisect()
와 insort()
함수를 제공한다. bisect()
는 이진 탐색으로 인덱스를 가져오고, insort()
는 정렬된 시퀀스안에 항목을 삽입한다.
각 함수는 lo, hi인자를 통해 검색 영역을 좁힐 수 있고, 디폴트는 lo = 0, hi = len(sequence)
이는 기본적으로 찾는 key보다 작거나 같은 것중 가장 큰것을 반환한다. 반대로 크거나 같은 것중 가장 작은것을 반환하는 것은 bisect_left이다. 다른 언어 기준으로 각각 lower_bound, upper_bound
바이트 코드 보기
1 |
|
을 통해 문장이 실제로 어떤 바이트 코드로 변환되는지 볼 수 있다.
메모리 뷰 사용하기
C의 union혹은 다른 타입으로의 포인터 케스팅과 같다.
1 |
|