파이썬에서 시퀀스(sequence)는 데이터를 순서대로 저장하는 구조를 말한다. 여기에는 여러 타입의 데이터가 포함될 수 있으며, 각 요소는 순서를 가지고 인덱스로 접근할 수 있다.
저장하는 데이터의 타입과 저장 방식에 따라 두가지로 나눈다. (컨테이너 시퀀스(Container Sequences), 균일 시퀀스(Flat Sequences))
컨테이너 시퀀스(Container Sequences)
컨테이너 시퀀스는 다양한 타입의 객체들을 담을 수 있는 시퀀스이다. 이 유형의 시퀀스는 객체에 대한 참조를 저장한다. 즉, 컨테이너 시퀀스 내의 각 항목은 다른 타입일 수 있다. 예를 들어, 리스트(list)와 튜플(tuple)은 컨테이너 시퀀스의 예시이다. 이들은 숫자, 문자열, 리스트 등 어떤 타입의 객체라도 담을 수 있다.
균일 시퀀스(Flat Sequences)
균일 시퀀스는 단일 타입의 값들만을 저장하는 시퀀스이다. 이 유형의 시퀀스는 메모리에 연속적으로 저장되며, 각 항목이 동일한 크기를 가진다. 균일 시퀀스는 보통 더 적은 메모리를 사용하고, 저장된 요소에 접근하는 속도가 빠르다는 특징이 있다. 문자열(str), 바이트(bytes), 바이트 배열(bytearray) 그리고 array.array와 같은 타입이 균일 시퀀스의 예시이다. 이들은 같은 타입의 데이터만 저장할 수 있다.
요약
- 컨테이너 시퀀스: 다양한 타입의 객체들을 담을 수 있으며, 객체에 대한 참조를 저장함. (예: 리스트, 튜플)
- 균일 시퀀스: 단일 타입의 데이터만을 저장하며, 메모리에 연속적으로 저장됨. (예: 문자열, 바이트)
객체가 한 번 생성된 후에 그 내용을 변경할 수 있는지 여부에 기반하는 방식으로 나눌 수도 있다. (가변 시퀀스(Mutable Sequences), 불변 시퀀스(Immutable Sequences))
가변 시퀀스 (Mutable Sequences)
가변 시퀀스는 생성된 후에도 그 내용이 변경될 수 있는 시퀀스를 말한다. 이러한 특성 때문에 가변 시퀀스는 데이터를 동적으로 조작할 때 매우 유용하다. 가변 시퀀스의 대표적인 예시로는 리스트(list)와 바이트 배열(bytearray)이 있다.
- 리스트(list): 파이썬의 가장 유연한 데이터 구조 중 하나로, 다양한 타입의 데이터를 순서대로 저장할 수 있다. 리스트는 요소를 추가(append()), 삭제(remove(), pop()), 변경할 수 있어서 데이터의 동적 관리가 가능하다.
- 바이트 배열(bytearray): 바이트의 가변 시퀀스로, 바이너리 데이터를 수정할 필요가 있을 때 사용된다. 파일 처리나 네트워크 통신에서 바이너리 데이터를 다룰 때 유용하다.
가변 시퀀스의 장점은 유연성에 있다. 프로그램 실행 중에 데이터 구조를 변경할 수 있으므로 다양한 알고리즘과 데이터 처리 요구사항에 맞출 수 있다. 하지만, 이러한 유연성은 주의 깊은 관리가 필요하다. 가변 객체는 데이터가 의도치 않게 변경될 위험이 있으므로, 특히 여러 함수나 모듈에 걸쳐 공유될 때는 이러한 부작용을 주의해야 한다.
불변 시퀀스 (Immutable Sequences)
불변 시퀀스는 생성된 후에는 내용을 변경할 수 없다. 이는 불변 시퀀스에 포함된 데이터가 안전하게 보존됨을 의미한다. 불변 시퀀스의 대표적인 예로는 문자열(str)과 튜플(tuple)이 있다.
- 문자열(str): 텍스트 데이터를 표현하는 데 사용되며, 한 번 생성되면 그 내용을 변경할 수 없다. 문자열을 변경하려고 하면, 변경된 새로운 문자열 객체가 생성된다.
- 튜플(tuple): 리스트와 유사하지만 한 번 생성되면 변경할 수 없는 시퀀스다. 튜플은 프로그램 내에서 변경되지 않아야 하는 데이터를 저장하는 데 적합하다.
불변 시퀀스의 장점은 데이터의 안정성과 예측 가능성에 있다. 불변 객체는 실수로 데이터가 변경되는 것을 방지하며, 프로그램의 동작을 더 예측 가능하게 만든다. 특히, 멀티스레드 환경에서는 데이터 경쟁 상황(race condition)을 방지하는 데 도움이 된다.
지능형 리스트(List Comprehension) VS 제너레이터 표현식
지능형 리스트(List Comprehension)는 파이썬에서 반복문과 조건문을 사용하여 새로운 리스트를 간단하고 직관적으로 생성할 수 있는 방법이다. 기본 형태는 [expression for item in iterable if condition]로, 여기서 expression은 결과 리스트에 저장될 값, item은 iterable에서 순차적으로 가져오는 각 요소, 그리고 if condition은 해당 요소를 결과에 포함시킬지 결정하는 조건이다. 예를 들어, squares = [x**2 for x in range(10)]는 0부터 9까지의 숫자의 제곱으로 이루어진 리스트를 만든다.
squares_even = [x**2 for x in range(10) if x % 2 == 0]
print(squares_even) # [0, 4, 16, 36, 64]
제너레이터 표현식은 지능형 리스트와 매우 비슷한 문법을 사용하지만, 대괄호([]) 대신 소괄호(())를 사용하여 생성된다. 제너레이터 표현식은 전체 리스트를 한 번에 메모리에 로딩하는 대신, 필요할 때마다 항목을 하나씩 생성(즉, "지연 평가")하는 방식으로 작동합니다. 이는 큰 데이터를 처리할 때 메모리를 절약할 수 있게 해준다. 예: (x**2 for x in range(10))은 0부터 9까지 숫자의 제곱을 생성하는 제너레이터를 만든다. 제너레이터는 이터레이터 프로토콜을 따르므로, for 루프나 next() 함수를 사용하여 접근할 수 있다.
squares_gen = (x**2 for x in range(10))
for value in squares_gen:
print(value) # 0, 1, 4, 9, 16, 25, 36, 49, 64, 81
지능형 리스트와 제너레이터 표현식은 파이썬 코드를 더 간결하고 읽기 쉽게 만들어주는 훌륭한 도구들이며 파이썬에서 데이터를 처리하는 데 있어 매우 유용하지만, 사용 사례에 따라 적절한 선택이 필요하다. 지능형 리스트는 결과를 바로 사용해야 할 때 유리하며, 제너레이터 표현식은 데이터 처리에 있어 실제 요소를 메모리에 모두 저장하지 않기 때문에 메모리 사용을 최소화해야 할 때 더 적합하다.
튜플(tuple)
튜플(tuple)은 파이썬의 기본 자료구조 중 하나로, 여러 값들을 순서대로 묶어서 저장하는 데 사용된다. 튜플은 불변(immutable)하기 때문에, 한 번 생성된 후에는 그 내용을 변경할 수 없다. 이러한 특성 때문에 튜플은 다양한 용도로 사용되는데, 특히 "레코드"로서의 역할을 할 때 매우 유용하다.
레코드로서의 튜플
"레코드"란 여러 필드(데이터 조각)를 조합해서 하나의 의미 있는 단위를 만든 것을 말한다. 예를 들어, 학생에 대한 정보를 저장하는 레코드에는 이름, 나이, 학번 등이 포함될 수 있다. 튜플을 사용하면 이러한 레코드를 간결하고 효율적으로 표현할 수 있다. 튜플의 각 요소는 레코드의 한 필드를 나타내며, 튜플 전체가 하나의 레코드를 나타낸다.
튜플의 장점
- 불변성: 튜플의 불변성은 데이터가 의도치 않게 변경되는 것을 방지한다. 이는 특히 다양한 함수나 모듈에 걸쳐 데이터를 전달할 때 유용하다.
- 순서가 있음: 튜플의 요소는 순서를 가지므로, 각 요소는 특정 필드의 위치로 고정된다. 이는 데이터를 해석하고 사용하는 데 있어 오류를 줄여준다.
- 해시 가능: 튜플은 불변 객체이므로 해시 가능(hashable)하다. 이는 튜플을 딕셔너리의 키나 집합의 요소로 사용할 수 있음을 의미한다.
레코드로서 튜플 사용 예
student = ("Jane Doe", 20, "CS101")
print(student)
Named Tuples
표준 튜플은 위치를 통해 각 필드에 접근하기 때문에, 때때로 코드의 가독성을 저하시킬 수 있다. 파이썬은 이를 개선하기 위해 collections.namedtuple을 제공한다. Named tuple은 튜플의 각 위치에 이름을 할당할 수 있게 해주어, 필드에 이름으로 접근할 수 있다. 이를 통해, 가독성과 사용 편의성 측면에서의 이점이 있고, 코드의 유지 보수성을 높이는 데 기여하며, 필드에 이름을 할당함으로써 데이터에 대한 명확한 설명을 제공한다.
from collections import namedtuple
Student = namedtuple('Student', ['name', 'age', 'course'])
student = Student("John Doe", 22, "CS102")
print(student.name)
레코드로서의 튜플과 named tuple은 파이썬에서 데이터를 구조화하고 안전하게 관리하는 효율적인 방법을 제공한다.
튜플 언패킹(tuple unpacking)
튜플이나 리스트와 같은 시퀀스에서 여러 변수에 동시에 값을 할당하는 과정을 말한다. 이 기능은 파이썬의 매우 유용하고 강력한 기능 중 하나로, 코드를 더 간결하고 읽기 쉽게 만들어준다.
튜플 언패킹은 병렬 할당(Parallel Assignment)을 할 때 가장 눈에 띈다. 병렬할당이란 파이썬에서 여러 변수에 동시에 값을 할당하는 기법을 말한다. 이 방식을 사용하면, 여러 변수를 동시에 초기화하거나, 값을 교환하는 등의 작업을 한 줄의 코드로 간단하게 수행할 수 있다.
# 기본 예
t = (1, 2)
a, b = t
print(a) # 1 출력
print(b) # 2 출력
# 변수 값 교환
a, b = b, a
# 병렬 할당과 튜플 언패킹
t = (1, 2, 3)
a, b, c = t
확장된 언패킹
* 연산자를 사용한 확장된 튜플 언패킹 기능도 제공된다. 이를 사용하면, 시퀀스의 일부를 한 변수에 할당하고 나머지를 다른 변수에 할당할 수 있다.
t = (1, 2, 3, 4, 5)
a, *b, c = t
print(a) # 1 출력
print(b) # [2, 3, 4] 출력
print(c) # 5 출력
언패킹을 사용하여 반환값 받기
def calc_operations(x, y):
return x + y, x - y # 합과 차를 튜플 형태로 반환
sum_result, diff_result = calc_operations(10, 5)
print("Sum:", sum_result) # Sum: 15
print("Difference:", diff_result) # Difference: 5
모든 코드는 github에 저장되어 있습니다.
'Python study' 카테고리의 다른 글
텍스트(text)와 바이트(byte) (0) | 2024.05.04 |
---|---|
딕셔너리(dictionary)와 집합(set) (0) | 2024.04.29 |
시퀀스(sequence) - 슬라이싱(slicing), bisect, 다른 시퀀스 (2) | 2024.04.25 |
Python Special method (magic method) (0) | 2024.03.18 |
Variables and memory (0) | 2023.08.01 |