본문 바로가기
AI 오케스트레이션 프리코스

SK네트웍스 Family 엔코아 AI 오케스트레이션 프리코스 3|파이썬 리스트·튜플·딕셔너리·세트

by 랩보다 AI 더 잘해지기 2026. 7. 24.
728x90

파이썬에서 여러 개의 데이터를 관리하는 방법

이번 AI 오케스트레이션 프리코스에서는 여러 개의 데이터를 하나로 묶어 관리하는 파이썬 자료형을 학습했다.

앞서 문자열을 통해 순서가 있는 시퀀스 자료형과 값을 수정할 수 없는 불변 객체의 개념을 살펴봤다면, 이번에는 다음 네 가지 자료형의 특징과 사용법을 배웠다.

  • 리스트(List)
  • 튜플(Tuple)
  • 딕셔너리(Dictionary)
  • 세트(Set)

네 자료형은 모두 여러 개의 값을 저장할 수 있지만, 데이터를 저장하고 찾는 방법이 서로 다르다. 따라서 무조건 하나만 사용하는 것이 아니라 데이터의 성격에 맞는 자료형을 선택해야 한다.


1. 리스트: 자유롭게 수정할 수 있는 자료형

리스트는 여러 개의 값을 순서대로 저장하는 자료형이다. 대괄호 [] 안에 값을 쉼표로 구분해 작성한다.

numbers = [1, 2, 3, 4]

리스트는 파이썬에서 가장 유연한 자료형 중 하나다. 숫자와 문자열뿐 아니라 다른 리스트도 요소로 저장할 수 있다.

data = [1, "Python", True, [10, 20]]

리스트의 가장 중요한 특징은 가변 자료형이라는 점이다.

가변이라는 것은 리스트를 만든 뒤에도 요소를 추가하거나 수정하고 삭제할 수 있다는 뜻이다.

인덱싱과 슬라이싱

리스트는 저장된 값에 순서가 있으므로 인덱스를 이용할 수 있다.

numbers = [10, 20, 30, 40]

print(numbers[0])     # 10
print(numbers[-1])    # 40
print(numbers[1:3])   # [20, 30]

인덱스는 0부터 시작하며, 음수 인덱스를 사용하면 뒤에서부터 접근할 수 있다.

리스트 요소 수정하기

인덱스를 이용하면 특정 요소를 수정할 수 있다.

numbers = [10, 20, 30]

numbers[1] = 200

print(numbers)
# [10, 200, 30]

슬라이싱을 사용하면 여러 개의 요소도 한 번에 바꿀 수 있다.

letters = ["c", "d", "e"]

letters[0:2] = ["a", "b"]

print(letters)
# ['a', 'b', 'e']

강의에서는 같은 개수의 요소로 교체하는 예제를 다뤘지만, 파이썬의 리스트 슬라이스 대입은 교체하는 값의 개수가 달라도 사용할 수 있다.

letters = ["a", "b", "c"]

letters[1:2] = ["x", "y"]

print(letters)
# ['a', 'x', 'y', 'c']

리스트 더하기와 곱하기

리스트끼리 더하면 두 리스트가 하나로 연결된다.

a = [1, 2]
b = [3, 4]

print(a + b)
# [1, 2, 3, 4]

리스트에 숫자를 곱하면 요소가 해당 횟수만큼 반복된다.

print([1, 2] * 3)
# [1, 2, 1, 2, 1, 2]

다만 연산 결과를 변수에 다시 저장하지 않으면 원래 리스트는 바뀌지 않는다.

numbers = [1, 2]

numbers * 3
print(numbers)
# [1, 2]

원래 리스트까지 변경하려면 다시 할당해야 한다.

numbers = numbers * 3

2. 리스트에서 자주 사용하는 메서드

메서드는 특정 자료형이 사용할 수 있도록 만들어진 기능이다. 리스트 변수 뒤에 점을 찍어 사용한다.

리스트변수.메서드()

요소 추가하기

append()는 리스트 마지막에 요소 하나를 추가한다.

numbers = [1, 2, 3]

numbers.append(4)

print(numbers)
# [1, 2, 3, 4]

insert()는 원하는 인덱스 위치에 요소를 추가한다.

numbers.insert(0, 0)

print(numbers)
# [0, 1, 2, 3, 4]

extend()는 다른 리스트의 요소들을 현재 리스트 뒤에 추가한다.

numbers.extend([5, 6])

print(numbers)
# [0, 1, 2, 3, 4, 5, 6]

append([5, 6])을 사용하면 리스트 자체가 하나의 요소로 들어가지만, extend([5, 6])을 사용하면 5와 6이 각각의 요소로 추가된다는 차이가 있다.

요소 삭제하기

remove()는 지정한 값과 일치하는 첫 번째 요소를 삭제한다.

numbers = [1, 2, 2, 3]

numbers.remove(2)

print(numbers)
# [1, 2, 3]

pop()은 기본적으로 마지막 요소를 삭제하면서 삭제한 값을 돌려준다.

numbers = [1, 2, 3]

removed_number = numbers.pop()

print(removed_number)  # 3
print(numbers)         # [1, 2]

clear()는 리스트의 모든 요소를 삭제한다.

numbers.clear()

print(numbers)
# []

요소 찾기와 정렬하기

index()는 지정한 값이 처음 등장하는 인덱스를 알려준다.

numbers = [10, 20, 30]

print(numbers.index(20))
# 1

count()는 지정한 값이 리스트에 몇 개 있는지 계산한다.

numbers = [1, 1, 2, 3]

print(numbers.count(1))
# 2

sort()는 리스트를 오름차순으로 정렬한다.

numbers = [3, 1, 2]

numbers.sort()

print(numbers)
# [1, 2, 3]

reverse()는 정렬이 아니라 현재 순서를 반대로 뒤집는다.

numbers = [3, 1, 2]

numbers.reverse()

print(numbers)
# [2, 1, 3]

sort()와 reverse()는 리스트 자체를 변경하지만, 실행 결과로 새로운 리스트를 반환하지는 않는다. 따라서 다음과 같이 작성하면 None이 출력된다.

print(numbers.sort())
# None

정렬된 값을 확인하려면 메서드를 먼저 실행한 뒤 리스트를 따로 출력해야 한다.


3. 중첩 리스트와 스택 구조

리스트 안에는 다른 리스트도 저장할 수 있다. 이를 중첩 리스트라고 한다.

letters = ["a", "b", "c"]
numbers = [1, 2, 3]

data = [letters, numbers]

중첩된 리스트의 내부 요소에 접근하려면 인덱싱을 연속으로 사용한다.

print(data[0])     # ['a', 'b', 'c']
print(data[0][1])  # b
print(data[1][2])  # 3

첫 번째 인덱스는 바깥쪽 리스트의 요소를 선택하고, 두 번째 인덱스는 안쪽 리스트의 요소를 선택한다.

리스트를 스택처럼 사용하기

리스트의 append()와 pop()을 이용하면 스택 구조도 만들 수 있다.

스택은 마지막에 들어온 값이 가장 먼저 나오는 구조다. 이를 LIFO(Last In, First Out)라고 한다.

접시를 차곡차곡 쌓은 뒤 맨 위의 접시부터 꺼내는 모습과 비슷하다.

stack = [3, 4, 5]

stack.append(6)
stack.append(7)

print(stack.pop())  # 7
print(stack.pop())  # 6
print(stack)        # [3, 4, 5]

4. 튜플: 한 번 만들면 수정할 수 없는 자료형

튜플은 리스트처럼 여러 개의 값을 순서대로 저장한다. 하지만 리스트와 달리 불변 자료형이다.

numbers = (1, 2, 3)

리스트는 대괄호를 사용하지만 튜플은 소괄호 ()를 사용한다.

튜플도 시퀀스 자료형이므로 인덱싱과 슬라이싱이 가능하다.

numbers = (10, 20, 30, 40)

print(numbers[0])    # 10
print(numbers[1:3])  # (20, 30)

하지만 요소를 수정하거나 추가하고 삭제할 수는 없다.

numbers[0] = 100
# TypeError 발생

따라서 리스트에서 사용할 수 있었던 append(), insert(), remove() 같은 메서드를 튜플에서는 사용할 수 없다.

소괄호를 생략할 수 있는 튜플

튜플은 쉼표를 사용하면 소괄호를 생략할 수도 있다.

languages = "Python", "Java", "JavaScript"

print(type(languages))
# <class 'tuple'>

튜플을 구분하는 핵심은 소괄호보다 쉼표라고 볼 수 있다.

요소가 하나인 튜플을 만들 때도 쉼표가 필요하다.

one_value = (1,)

print(type(one_value))
# <class 'tuple'>

쉼표 없이 (1)만 작성하면 튜플이 아니라 일반 정수로 처리된다.

튜플은 언제 사용할까?

리스트가 더 자유로운데도 튜플을 사용하는 이유는 데이터가 실수로 변경되는 것을 막을 수 있기 때문이다.

예를 들어 좌표, 생년월일, 고정된 설정값처럼 실행 중에 바뀌면 안 되는 데이터를 저장할 때 튜플이 적합하다.

position = (100, 200)

튜플은 구조가 단순하기 때문에 리스트보다 일반적으로 메모리 사용량이 적고 일부 작업에서 더 빠르게 동작할 수 있다.


5. 딕셔너리: 키와 값으로 데이터를 저장하는 자료형

딕셔너리는 데이터를 키(Key)값(Value)의 쌍으로 저장한다.

student = {
    "name": "홍길동",
    "age": 20,
    "major": "AI"
}

중괄호 {} 안에서 키와 값은 콜론 :으로 연결하고, 각각의 요소는 쉼표로 구분한다.

딕셔너리는 숫자 인덱스 대신 키를 이용해 값에 접근한다.

print(student["name"])
# 홍길동

키는 사물함 번호나 사람의 이름표와 비슷하다. 원하는 값을 찾기 위한 고유한 표시라고 이해할 수 있다.

현재 파이썬의 딕셔너리는 입력 순서를 보존하지만, 리스트처럼 숫자 인덱스를 이용해 접근하는 자료형은 아니다.

키는 중복될 수 없다

하나의 딕셔너리에서 같은 키를 여러 번 작성하면 마지막 값이 남는다.

data = {
    "name": "철수",
    "name": "영희"
}

print(data)
# {'name': '영희'}

키는 특정 값을 구분해야 하므로 중복될 수 없다.

딕셔너리 값 수정과 추가

기존 키에 새로운 값을 할당하면 값이 수정된다.

student["age"] = 21

존재하지 않는 키에 값을 할당하면 새로운 요소가 추가된다.

student["city"] = "서울"

딕셔너리 요소 삭제

del을 사용하면 특정 키와 연결된 요소를 삭제할 수 있다.

del student["major"]

없는 키에 대괄호로 접근하면 KeyError가 발생하므로 실제 코드에서는 키가 존재하는지 먼저 확인하는 습관이 필요하다.

print("name" in student)
# True

딕셔너리에 바로 in을 사용하면 키의 존재 여부를 확인한다.

값의 존재 여부를 확인하려면 values()를 사용한다.

print("홍길동" in student.values())

딕셔너리 키와 값의 조건

딕셔너리의 값에는 리스트, 튜플, 딕셔너리 등 거의 모든 자료형을 사용할 수 있다.

하지만 키에는 실행 중 내용이 바뀔 수 없는 자료형을 사용해야 한다.

키로 사용할 수 있는 대표적인 자료형은 다음과 같다.

  • 문자열
  • 정수와 실수
  • 불리언
  • 튜플

리스트나 딕셔너리처럼 변경 가능한 자료형은 키로 사용할 수 없다.

빈 딕셔너리 만들기

빈 중괄호를 사용하거나 dict() 함수를 사용할 수 있다.

data1 = {}
data2 = dict()

zip()으로 딕셔너리 만들기

키 목록과 값 목록이 따로 있다면 zip()과 dict()를 이용해 하나의 딕셔너리로 만들 수 있다.

keys = ["name", "age", "city"]
values = ["홍길동", 20, "서울"]

student = dict(zip(keys, values))

print(student)
# {'name': '홍길동', 'age': 20, 'city': '서울'}

zip()은 같은 위치의 요소끼리 짝을 만들어 주는 역할을 한다.


6. 세트: 중복을 허용하지 않는 집합 자료형

세트는 수학에서 사용하는 집합과 비슷한 자료형이다.

numbers = {1, 2, 3, 4}

세트의 가장 중요한 특징은 다음 두 가지다.

첫째, 중복된 값을 저장하지 않는다.

numbers = {1, 1, 2, 2, 3}

print(numbers)
# {1, 2, 3}

둘째, 요소의 순서를 기준으로 사용하지 않는다. 따라서 리스트나 튜플처럼 인덱싱할 수 없다.

numbers[0]
# TypeError 발생

세트의 출력 순서는 실행 환경에 따라 다르게 보일 수 있으므로 특정 순서에 의존해서는 안 된다.

빈 세트 만들기

빈 중괄호 {}는 세트가 아니라 빈 딕셔너리가 된다.

data = {}

print(type(data))
# <class 'dict'>

빈 세트는 반드시 set()으로 만들어야 한다.

numbers = set()

세트 요소 추가와 삭제

add()는 세트에 요소 하나를 추가한다.

numbers = set()

numbers.add(1)
numbers.add(1)

print(numbers)
# {1}

같은 값을 여러 번 추가해도 하나만 저장된다.

remove()는 지정한 요소를 삭제하지만, 없는 값을 삭제하려 하면 오류가 발생한다.

numbers.remove(1)

discard()도 요소를 삭제하지만, 값이 없어도 오류가 발생하지 않는다.

numbers.discard(100)

pop()은 세트에서 임의의 요소 하나를 제거하면서 반환한다. 세트에는 순서가 없으므로 리스트처럼 마지막 요소가 삭제된다고 생각하면 안 된다.

clear()는 세트의 모든 요소를 삭제한다.


7. 세트의 집합 연산

세트는 수학의 집합처럼 합집합, 교집합, 차집합을 계산할 수 있다.

a = {1, 2, 3, 4}
b = {2, 4, 5}

합집합

두 세트의 모든 요소를 합치되 중복은 제거한다.

print(a | b)
print(a.union(b))

# {1, 2, 3, 4, 5}

교집합

두 세트에 공통으로 포함된 요소를 구한다.

print(a & b)
print(a.intersection(b))

# {2, 4}

차집합

앞쪽 세트에는 있지만 뒤쪽 세트에는 없는 요소를 구한다.

print(a - b)
print(a.difference(b))

# {1, 3}

부분집합과 상위집합

issubset()은 한 세트가 다른 세트의 부분집합인지 확인한다.

a = {1, 2}
b = {1, 2, 3}

print(a.issubset(b))
# True

issuperset()은 한 세트가 다른 세트를 모두 포함하는지 확인한다.

print(b.issuperset(a))
# True

isdisjoint()는 두 세트에 겹치는 요소가 없는지 확인한다.

a = {1, 2}
b = {3, 4}

print(a.isdisjoint(b))
# True

8. 네 가지 자료형 비교

자료형작성 방법순서 기반 접근중복 허용요소 변경

리스트 [1, 2, 3] 가능 가능 가능
튜플 (1, 2, 3) 가능 가능 불가능
딕셔너리 {"key": "value"} 키로 접근 키는 불가능 가능
세트 {1, 2, 3} 불가능 불가능 가능

자료형을 선택할 때는 다음과 같이 생각할 수 있다.

  • 순서가 있고 값을 자유롭게 수정해야 한다면 리스트
  • 순서는 있지만 값이 바뀌면 안 된다면 튜플
  • 이름표처럼 키를 이용해 값을 찾고 싶다면 딕셔너리
  • 중복을 제거하거나 집합 계산이 필요하다면 세트

영상 학습과 실습 내용 구분

이번 프리코스에서는 강사가 JupyterLab에서 코드를 실행하며 각 자료형의 생성, 조회, 수정, 삭제 방법을 보여줬다.

리스트에서는 인덱싱과 슬라이싱, 여러 메서드, 중첩 리스트와 스택 구조를 확인했다. 튜플에서는 불변성 때문에 요소 변경이 불가능한 모습을 살펴봤다.

딕셔너리에서는 키를 이용한 접근과 값 수정, 새로운 요소 추가, zip()을 활용한 생성 방법을 학습했다. 세트에서는 중복 제거와 집합 연산이 어떻게 동작하는지 확인했다.

이번 회고는 영상에서 다룬 강의 예제를 기준으로 정리했으며, 별도의 개인 프로젝트나 응용 프로그램을 제작한 내용은 포함하지 않았다.


이번 학습을 통해 새롭게 이해한 점

이전에는 여러 개의 값을 저장해야 할 때 주로 리스트만 떠올렸다. 하지만 이번 강의를 통해 자료형마다 만들어진 목적이 다르다는 점을 이해했다.

특히 리스트와 튜플은 모양이 비슷하지만 값을 변경할 수 있는지에 따라 사용 목적이 달랐다. 딕셔너리는 순서가 아니라 키를 기준으로 데이터를 관리하기 때문에 실제 서비스의 회원 정보나 상품 정보처럼 이름이 있는 데이터를 저장할 때 유용해 보였다.

세트는 중복을 자동으로 제거한다는 특징뿐 아니라 합집합과 교집합 같은 계산을 간단하게 처리할 수 있다는 점이 인상적이었다.

결국 중요한 것은 문법을 외우는 것보다 현재 다루는 데이터가 어떤 성격인지 먼저 생각하는 것이다.


앞으로 복습할 부분

리스트 메서드는 종류가 많기 때문에 각각의 반환값과 원본 리스트의 변경 여부를 구분해서 복습할 필요가 있다.

특히 append()와 extend(), remove()와 pop(), sort()와 reverse()의 차이를 직접 코드를 실행하며 다시 확인해 봐야겠다.

딕셔너리에서는 키로 사용할 수 있는 자료형의 조건과 zip()의 동작 방식을 복습하고, 세트에서는 집합 연산 기호와 메서드를 함께 정리할 예정이다.


핵심 정리

리스트는 순서가 있으며 요소를 자유롭게 수정할 수 있는 가변 자료형이다.

튜플은 순서가 있지만 요소를 수정할 수 없는 불변 자료형이다.

딕셔너리는 키와 값의 쌍으로 데이터를 저장하며, 키를 이용해 원하는 값에 접근한다.

세트는 순서가 없고 중복을 허용하지 않으며, 합집합과 교집합 같은 집합 연산에 적합하다.

이번 학습을 통해 여러 개의 값을 저장한다는 공통점만 보고 자료형을 선택하는 것이 아니라, 데이터의 순서·중복·변경 가능성·접근 방법을 함께 고려해야 한다는 것을 배웠다.

댓글