오늘은 파이썬의 꽃이라고 할 수 있는 리스트, 세트, 딕셔너리의 고급 활용법에 대해 알아보려고 합니다. 이 세 가지 자료구조는 파이썬 프로그래밍의 근간을 이루는 요소들인데요, 이들을 제대로 활용하면 코드의 효율성과 가독성을 상당히 높일 수 있을 거예요.
파이썬 리스트(List) 세트(Set) 딕셔너리(Dictionary) 고급 활용법
1. 파이썬 리스트(List)
리스트 컴프리헨션
리스트 컴프리헨션은 파이썬의 강력한 기능 중 하나입니다. 복잡한 for 루프를 한 줄로 압축할 수 있죠. 한 줄의 간결한 문법으로도 꽤 복잡한 연산을 수행할 수 있게 해 줍니다. 흔히 단순히 for 문을 줄이는 데 사용하지만, 조건문을 함께 쓰는 방식 등을 통해 코드 가독성과 유지보수성까지 높일 수 있습니다.
기본 형태
numbers = [1, 2, 3, 4, 5]
squares = [x**2 for x in numbers] # [1, 4, 9, 16, 25]
- 위와 같이 단순히 제곱을 구하는 용도로 쓸 수도 있고, 이를 더 확장하면 다음과 같은 패턴을 적용할 수 있습니다.
조건문 결합
even_squares = [x**2 for x in numbers if x % 2 == 0] # [4, 16]
- x % 2 == 0인 숫자만 골라서 제곱을 취해 새로운 리스트를 만들었습니다. 기존 `for` 문과 `if` 문을 이중으로 쓰는 것에 비해 훨씬 짧고 깔끔해집니다.
다차원 리스트(중첩 리스트)
데이터 처리가 복잡해지면 리스트 안에 리스트를 넣어 다차원 구조로 사용하는 경우가 많습니다. 예를 들어 2차원 리스트가 2차원 배열이나 표 형태의 데이터를 나타낼 때 유용합니다.
중첩 리스트
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# 행 단위로 합계 구하기
row_sums = [sum(row) for row in matrix] # [6, 15, 24]
- 이렇듯 한 행씩 꺼내와 sum()을 적용하면 쉽게 각 행의 합계를 구할 수 있습니다.
리스트 슬라이싱
리스트 슬라이싱은 list[start:end:step] 형태로 특정 구간의 요소를 추출하는 기능입니다.
양 끝단 제거
data = [10, 20, 30, 40, 50, 60]
# 처음과 마지막 요소를 제외한 리스트
trimmed = data[1:-1] # [20, 30, 40, 50]
- 길이가 긴 리스트에서 특정 부분만 잘라서 보고 싶을 때 편리합니다.
거꾸로 뒤집기
reversed_data = data[::-1] # [60, 50, 40, 30, 20, 10]
- step 값을 -1로 주면 간단히 역순 정렬된 리스트를 얻을 수 있습니다.
메서드 활용
리스트는 중간 삽입과 삭제에 취약하지만, 뒤에서 넣고 빼는 작업은 비교적 빠릅니다. 이런 특성을 알고 메서드를 적절히 활용하면 불필요한 연산을 줄일 수 있습니다.
append()와 extend()
# append()는 리스트의 끝에 단일 객체를 추가
my_list = [1, 2, 3]
my_list.append(4) # [1, 2, 3, 4]
# extend()는 리스트의 끝에 다른 시퀀스의 모든 항목을 추가
my_list.extend([5, 6]) # [1, 2, 3, 4, 5, 6]
- append()와 extend()는 비슷해 보이지만, 동작 방식에 차이가 있습니다. 특히 extend()를 써서 한 번에 여러 요소를 붙이면 루프를 여러 번 도는 수고를 덜 수 있습니다.
pop()의 위치 지정
# pop()으로 마지막 요소 제거
last_element = my_list.pop() # 6
# pop(index)를 통해 중간 요소 제거 가능
second_element = my_list.pop(1) # 기존 리스트에서 인덱스 1 위치의 값
- 인덱스를 지정하면 원하는 위치의 요소를 제거해 반환합니다. 하지만 리스트 중간 요소를 자주 제거해야 한다면, 리스트 대신 다른 자료 구조(예: collections.deque)를 고려하는 것이 성능 면에서 나을 수 있습니다.
세트(Set)
세트는 중복을 허용하지 않으며, 순서가 보장되지 않는 자료 구조입니다. 같은 데이터가 여러 개 들어갈 일이 없다면, 세트를 쓰는 것이 메모리나 검색 속도 면에서 유리한 경우가 많습니다.
세트 생성
my_set = {1, 2, 3, 3, 2}
print(my_set) # {1, 2, 3}
- 중복된 값이 자동으로 제거되는 것을 확인할 수 있습니다.
멤버십 검사
if 2 in my_set:
print("2가 세트에 들어 있습니다.")
- 세트는 내부적으로 해시 테이블을 사용하므로, 원소가 들어있는지 검사할 때 리스트보다 훨씬 빠른 경우가 많습니다.
중복 제거와 집합 연산(합집합, 교집합, 차집합)
파이썬의 세트는 수학에서 말하는 집합의 개념을 그대로 지원합니다. 이를 잘 이용하면 중복 제거 이상의 강력한 데이터를 다룰 수 있습니다.
합집합( `|` 혹은 `union()`)
set_a = {1, 2, 3}
set_b = {3, 4, 5}
union_set = set_a | set_b # {1, 2, 3, 4, 5}
- union() 메서드를 사용하면 같은 연산을 할 수 있습니다.
교집합( `&` 혹은 `intersection()`)
intersection_set = set_a & set_b # {3}
- 두 세트가 공유하는 원소만 추출됩니다.
차집합( `-` 혹은 `difference()` )
difference_set = set_a - set_b # {1, 2}
- 첫 번째 세트에만 존재하는 원소를 구할 수 있습니다.
세트 컴프리헨션(Set Comprehension)
리스트 컴프리헨션과 유사하게, 세트도 중괄호와 조건문 등을 조합해 한 줄로 새로운 세트를 만들 수 있습니다.
numbers = [1, 2, 2, 3, 4, 4, 5]
unique_even_squares = {x**2 for x in numbers if x % 2 == 0}
# numbers의 요소 중 짝수만 골라 제곱한 뒤, 중복을 자동으로 제거한 세트
- 이런 방식을 통해 리스트에서 중복을 제거하며 원하는 연산을 한 번에 수행할 수 있으므로, 간단한 데이터 전처리에 매우 효율적입니다.
블랙리스트 필터링
# 블랙리스트 아이디를 세트로 관리
blacklist = {"abuse123", "spamking", "hacker01"}
# 대량의 사용자 아이디 중 블랙리스트에 해당하는 아이디만 추출
users = ["john", "hacker01", "alice", "spamking", "ruby"]
filtered = [user for user in users if user in blacklist]
print(filtered) # ["hacker01", "spamking"]
- 블랙리스트를 리스트로 관리했다면 사용자 한 명씩 돌 때마다 전체 블랙리스트를 확인해야 하지만, 세트를 쓰면 해시 테이블을 통해 빠른 멤버십 검사가 가능합니다.
딕셔너리(Dictionary)
키와 값
딕셔너리는 키(key)와 값(value) 쌍으로 구성되며, 키에는 해시 가능한(immutable) 자료형만 사용할 수 있습니다. 값에는 어떠한 파이썬 객체도 넣을 수 있으므로, 필요에 따라 딕셔너리 안에 딕셔너리를 넣어 구조를 확장하기도 합니다.
person = {
"name": "Alice",
"age": 30,
"hobbies": ["reading", "travel", "photography"],
"address": {
"city": "Seoul",
"zip": "12345"
}
}
딕셔너리 메서드 심화 (items, keys, values, get 등)
딕셔너리는 자주 쓰이는 자료 구조인 만큼, 메서드가 다양합니다.
items()
for key, value in person.items():
print(key, value)
- (키, 값) 튜플 쌍을 순회할 수 있어, 여러 데이터를 빠르게 확인하거나 가공할 때 편리합니다.
keys()와 values()
# 키만 꺼내기
print(person.keys()) # dict_keys(['name', 'age', 'hobbies', 'address'])
# 값만 꺼내기
print(person.values()) # dict_values(['Alice', 30, ['reading', 'travel', 'photography'], {'city': 'Seoul', 'zip': '12345'}])
- 필요에 따라 키 목록, 값 목록만 빠르게 분리하여 처리할 수 있습니다.
get()
# 'gender'라는 키가 없으면 None 반환
print(person.get("gender")) # None
# 기본값 지정
print(person.get("gender", "N/A")) # N/A
- 딕셔너리에 존재하지 않는 키에 접근할 때 KeyError가 발생하는 것을 피하고 싶다면 get()을 사용하는 것이 편합니다.
딕셔너리 컴프리헨션(Dictionary Comprehension)
리스트 컴프리헨션이나 세트 컴프리헨션처럼, 딕셔너리에서도 한 줄로 새로운 딕셔너리를 생성할 수 있습니다.
numbers = [1, 2, 3, 4]
squares_dict = {x: x**2 for x in numbers}
# {1: 1, 2: 4, 3: 9, 4: 16}
리스트, 세트, 딕셔너리는 파이썬에서 가장 기본적이면서도 유용한 자료 구조입니다. 하지만 단순히 기본 문법만 알면 아쉬운 부분이 많습니다. 본문에서 소개한 고급 활용 기법과 예시를 잘 숙지해 두면, 실제 코딩을 할 때 훨씬 유연하고 효율적인 코드를 작성할 수 있을 것입니다.
'프로그래밍 언어 > Python' 카테고리의 다른 글
파이썬 데이터 클래스와 타이핑. 효율적인 코드 작성을 위한 고급 프로그래밍 - 고급 Python #6 (0) | 2025.01.10 |
---|---|
파이썬 Collections 모듈 가이드 Counter부터 deque까지 활용 방법 - 고급 Python #5 (0) | 2025.01.07 |
파이썬 제너레이터와 이터레이터 효율적인 대용량 데이터 처리와 메모리 최적화 - 고급 Python #3 (0) | 2024.12.27 |
메타클래스와 데코레이터로 배우는 파이썬 고급 프로그래밍 - 고급 Python #2 (0) | 2024.12.20 |
파이썬 함수형 프로그래밍과 람다 표현식 고계 함수와 실무 예제 - 고급 Python #1 (0) | 2024.12.17 |