[지식/이론][python] 내장 시퀀스
개요
파이썬 내장 시퀀스 자료구조는 다음의 속성을 띤다.
- 멤버십(membership) 연산: in 키워드를 사용.
- 크기(size) 함수 제공: len(seq)
- 슬라이싱(slicing) 속성: seq[i:j]
- 반복성(iterability): 반복문에 있는 데이터 순회 가능
시퀀스 (sequence)
파이썬에는 내장 시퀀스 데이터 자료형이 존재한다. 파이썬에는 다음의 4개의 내장 시퀀스 자료형을 가진다.
- 문자열
some_str = ""
- 튜플
some_tuple = ()
- 리스트
some_list = []
- 바이트 배열
some_byte_array = bytearray(b"")
- 바이트
some_byte = bytes([])
깊은 복사와 가변성
파이썬에는 가변(mutable) 객체 자료형과 불변(immutable) 객체 자료형이 존재하는데, 내장 시퀀스들은 다음과 같이 분류할 수 있다.
- 가변 객체 자료형: list, bytearray
- 불변 객체 자료형: tuple, str, byte
일반적으로 불변 객체 자료형이 가변 객체 자료형보다 더 효율적이라고 한다. 불변 객체의 경우 복제 및 비교 작업을 단순화할 수 있다.
파이썬에서의 모든 변수는 객체 참조(reference)이므로 가변 객체 복사 시 유의해야한다. 변수 a, b가 있고 복사를 위해 a = b라고 했다면 a는 사실 b가 참조하는 어떤 객체를 참조하게 된다. (a → 어떤 객체 ← b)
다음은 list의 얕은 복사 (shallow copy) 예이다.
a = [1, 2, 3]
b = a
b[0] = 4
print(a)
print(b)
print(id(a))
print(id(b))
[4, 2, 3]
[4, 2, 3]
2131607492736
2131607492736
변수 b에 변수 a의 값을 복사한 후, 변수 b의 일부를 다른 데이터로 바꾸고 있다. 그런데 a는 건드리지 않았음에도 a의 값도 덩달아 똑같이 바뀌고 말았다. 이는 a가 참조하는 객체와 b가 참조하는 객체가 다르지 않고, 서로 똑같은 객체를 참조하기 때문이다. 위 출력 결과의 id() 출력 결과를 보면 두 변수의 id가 똑같은데 이것이 두 변수가 같은 객체를 참조하고 있다는 뜻이다.
변수 b에서 데이터 일부를 바꿀 때 해당 데이터는 두 변수 모두에서 참조하고 있으므로 변수 a를 호출해도 변수 b에 의해 변경된 데이터가 그대로 출력되는 것이다. 마치 한 사람의 한국 이름이 ‘철수’이고, 영어 이름이 ‘James’인데, 두 이름 모두 똑같은 한 사람을 가리키고 있는 것과 마찬가지이다. (철수는 오른팔이 아프다 = James도 오른팔이 아프다)
이러한 경우가 얕은 복사이다. 이러한 현상은 파이썬 내 모든 가변 객체 자료형에서 발생한다.
만약 이러한 경우를 피하고자 한다면 한 변수의 값을 다른 변수에 복사하더라도 두 변수 모두 각자 참조하는 객체가 달라야한다. 이러한 방법으로 복사를 하는 것을 깊은 복사(deep copy)라 한다.
list의 경우, 깊은 복사를 위해서는 슬라이싱을 이용한다.
a = [1, 2, 3]
b = a[:] # 슬라이싱을 이용하여 깊은 복사
b[0] = 4
print(a)
print(b)
print(id(a))
print(id(b))
print(id(a) == id(b))
[1, 2, 3]
[4, 2, 3]
2237507115200
2237507116416
False
복사를 했음에도 두 변수의 id값이 서로 다르다. 즉, 두 변수는 깊은 복사에 의해 각자 참조하는 객체가 서로 다르게 되었다는 뜻이다.
set, dictionary의 경우 내장 메서드인 copy()를 이용한다.
a = {'hi', 'hello', 'greeting'}
b = a.copy()
b.remove('hello')
print(a)
print(b)
print(id(a))
print(id(b))
print(id(a) == id(b))
{'hi', 'hello', 'greeting'}
{'hi', 'greeting'}
2079672207168
2079672207616
False
다른 객체의 깊은 복사를 하려면 copy모듈의 deepcopy() 함수를 이용한다. (해당 모듈의 copy() 함수는 얕은 복사를 한다)
import copy
a = 'abc'
b = copy.copy(a)
c = copy.deepcopy(a)
슬라이싱 연산자
파이썬 시퀀스 자료형에서는 슬라이싱 연산자를 사용할 수 있는데, 문법은 다음과 같다.
seq[start]
seq[start:end]
seq[start:end:step]
오른쪽 맨 끝부터 데이터를 추출하고자 한다면 인덱스에 음수를 넣으면 된다. -1은 맨 오른쪽 데이터를 가리킨다.
Reference
[1] 지은이: 미아 스타인, 옮긴이: 최길우, “파이썬 자료구조와 알고리즘”, (2019, 한빛미디어)
[2]
12. 얕은 복사(shallow copy)와 깊은 복사(deep copy)
[3]
파이썬 코딩 도장: 47.3 bytes, bytearray 사용하기
This content is licensed under
CC BY-NC 4.0
댓글남기기