
싱글 데이터 타입에 이어서 여러 개의 데이터를 담는 데이터 타입은 크게 4가지로 나뉩니다.
1. 리스트 (List) : 순서가 있고, 중복이 허용되며, mutable
2. 튜플 (Tuple) : 순서가 있고, 중복이 허용되며, immutable
3. 세트 (Set) : 순서가 없고, 중복 허용되지 않습니다.
4. 딕셔너리 (dict): key, value 쌍으로 구성되며 3.7부터 저장 순서가 유지됩니다.
리스트
리스트는 [ ] 을 통해 만들며, 데이터(원소)들은 콤마(,)로 구분됩니다. 원소들은 어떠한 타입도 가능합니다.
참고로 마지막 원소 다음에 콤마(,)도 허용됩니다.
리스트는 아래와 같이 만듭니다.
animals = ['Dog', 'cat', 'bird', 'fish']여기서 요소에 접근할 때는 **인덱스(Index)**를 사용합니다. 리스트는 순서가 있기 때문입니다.
인덱스의 첫번째 원소는 0부터 시작합니다. (zero-base index)
print(animals[0]) # dog
print(animals[1]) # cat
print(animals[2]) # bird
print(animals[3]) # fish여기서 인덱스는 (리스트의 길이 - 1) 까지 존재하는데 그것을 넘으면, Out of Range 에러가 발생합니다.
animals[4] # list index out of range참고로 Python에서는 음수 인덱싱도 지원합니다. 예를 들어 animals[-1]은 맨 끝의 원소를 의미합니다.
animals[-1] # fish리스트는 요소의 변경이 가능한데 이러한 특징을 mutable 하다고 합니다.
예를 들어 요소의 3번째 요소를 mouse로 수정해봅시다.
animals[2] = 'mouse'
print(animals) # ['dog', 'cat', 'mouse', 'fish']리스트는 각 원소(데이터)에 중복값을 넣을 수 있습니다.
fruits = ['apple', 'banana', 'apple', 'kiwi']
print(fruits) # ['apple', 'banana', 'apple', 'kiwi']리스트는 데이터의 일부를 추출하는 슬라이싱 기능도 제공합니다.
[start:end:steps]의 범위 연산자를 사용하여 일부를 추출합니다.
먼저 다음과 같은 리스트가 있다고 가정합시다.
colors = ['red', 'orange', 'blue', 'green', 'white', 'black']인덱스 0부터 3까지의 데이터를 추출할 경우 아래와 같이 적습니다. 여기서 3번째 인덱스는 미포함됩니다.
print(colors[0:3]) # ['red', 'orange', 'blue']똑같은 연산으로 시작값이 원소의 시작(0)이라면 생략 가능합니다.
print(colors[:2]) # ['red', 'orange', 'blue']반면에 끝값이 원소의 끝이라면 역시 생략 가능합니다.
print(colors[2:]) # ['blue', 'green', 'white', 'black']인덱스는 범위를 벗어나면 Error가 발생하지만 슬라이싱은 값이 범위를 벗어나도 에러가 발생하지 않습니다.
end 값이 범위를 벗어날 경우, 범위 끝까지로 판단하고 start 값이 범위를 벗어날 경우, 빈 배열로 판단됩니다.
print(colors[1:10]) # ['orange', 'blue', 'green', 'white', 'black']steps 옵션은 optional한 옵션이며, 사용할 경우 건너뛰는 값입니다.
※ 슬라이싱이 거꾸로 갈 경우 steps = -1로 적용합니다.
print(colors[1:6:2]) # ['orange', 'green', 'black']리스트는 데이터(원소)를 리스트 뒤에 추가할 때 append() 메소드를 사용하며, 이는 원본 리스트 역시 변화됩니다.
참고로, 결과값은 None으로 반환됩니다.
animals.append('cow') # 결과값은 None입니다.
animals # ['dog', 'cat', 'mouse', 'fish', 'cow']리스트에서 + 연산을 통해 서로 리스트 원소들을 합칠 수 있습니다.
print(animals) # ['dog', 'cat', 'mouse', 'fish', 'cow']
print(colors) # ['red', 'orange', 'blue', 'green', 'white', 'black']
print(animals + colors) # ['dog', 'cat', 'mouse', 'fish', 'cow',
# 'red', 'orange', 'blue', 'green', 'white', 'black']리스트에서 * 연산을 통해 리스트 원소들을 반복할 수 있습니다.
print(animals * 2) # ['dog', 'cat', 'mouse', 'fish', 'cow', 'dog', 'cat', 'mouse',
# 'fish', 'cow']리스트는 n차원 (n=1,2,3,....) 리스트를 제공합니다.
1차원 리스트는 인덱스를 한번만 사용하는 리스트로써 그 깊이가 1인 리스트를 일컫습니다.
colors = ['red', 'orange', 'blue', 'green', 'white', 'black']2차원 이상의 리스트는 인덱스를 여러번 사용하는 리스트로써 리스트의 원소가 또 다른 리스트입니다.
그 깊이가 2 이상인 리스트입니다. 아래 2차원 리스트는 3x3 2차원 리스트로써 행렬이라고도 부릅니다.
data = [
[1, 2, 3],
[10, 20, 30],
[40, 50, 60]
]리스트는 정렬해주는 메소드를 제공해주며, sort() 메소드와 sorted() 메소드를 이용할 수 있습니다.
다음과 같은 리스트가 있다고 가정해봅니다.
animals = ['Dog', 'cat', 'bird', 'fish']sort() 메소드는 원본 리스트를 정렬된 형태로 바꿔줍니다.
animals.sort() # 반환값은 None입니다.
print(animals) # ['bird', 'cat', 'Dog', 'fish']또한, reverse 속성을 통해 역순으로 정렬할 수도 있습니다.
animals.sort(reverse=True) # 내림차순 정렬
print(animals) # ['fish', 'Dog', 'cat', 'bird']sorted() 메소드는 정렬된 후 결과를 리턴해줍니다. 하지만 원본 리스트에는 변화가 없습니다.
print(sorted(animals)) # ['bird', 'cat', 'Dog', 'fish']리스트는 in 연산자를 통해 어떤 요소가 리스트에 포함되어 있는지 bool 타입을 반환받을 수 있습니다.
print('fish' in animals) # True리스트와 문자열을 연결하여 설명하자면, 인덱싱과 슬라이싱 모두 가능하며, 리스트와 다르게 immutable 합니다.
my_str = 'Hello Python'
my_str[0] = 'Y' # immutable 하므로 요소를 수정할 수 없습니다.또한 sorted 함수를 통해 각 문자를 요소로 하여 정렬된 리스트를 만듭니다.
print(sorted(my_str)) # [' ', 'e', 'h', 'h', 'l', 'l', 'n', 'o', 'o', 'p', 't', 'y']문자열의 join 메소드에 대해 알아보면, 해당 문자열로 list 요소들을 서로 합칩니다.
animals = ['mouse', 'fish', 'dog', 'cow', 'cat']
"--".join(animals) # mouse--fish--dog--cow--cat문자열의 split 메소드에 대해 알아보면, str를 쪼개어 그것을 원소로 하는 리스트를 반환합니다.
my_str = "Hello Python 2026"
my_str.split() # ['Hello', 'Python', '2026']리스트에서 list 함수는 어떤 데이터 타입을 list로 형변환할 수 있습니다.
my_str = '2026-04-29'
print(list(my_str)) # ['2','0','2','6','-','0','4','-','2','9']튜플
콤마(,)로 구분된 집합 데이터 타입으로써 수정할 수 없는 immutable 특성을 가집니다.
튜플은 아래와 같이 만듭니다.
animals = ('dog', 'cat', 'dot', 'bird')하지만 원소 하나짜리 튜플을 만드려면, 반드시 원소 뒤에 콤마(,)를 붙여야 합니다.
animals = ('dog',)튜플은 리스트처럼 인덱싱과 슬라이싱을 할수는 있지만, immutable 하므로 원소를 수정할 수는 없습니다.
튜플은 주로 변경되지 말아야 할 데이터들이나, 복수의 값 전달 목적으로 사용합니다.
튜플은 **대입 연산자 언패킹(Assignment Unpacking)**을 지원합니다. Iterable 객체이므로, 여러 개의 변수에 대입 가능합니다.
여기서 Iterable 객체란, 객체 안에 있는 원소들을 줄 세워서 하나하나 추출할 수 있는 객체를 말합니다.
str, list, tuple, set, dict 등이 iterable 객체의 대표적인 예시입니다.
rec = [100, 200]
width, height = rec또한, * 연산자를 통해 iterable 객체를 언패킹할 수도 있습니다.
fruits = ['apple', 'banana', 'apple', 'kiwi']
new_fruits = [*fruits, 'mango'] # ['apple', 'banana', 'apple', 'kiwi', 'mango']세트
순서가 없으므로, 인덱싱이 불가능하며 중복 허용이 되지 않습니다.
세트를 만드는 방법은 아래와 같습니다.
animals = { "dog", "cat", "dog", "bird" } # {}를 통해 초기화하기 { "dog", "cat", "bird" }
animals_list = ["dog", "cat", "dog", "bird"]
print(set(animals_list)) # { "dog", "cat", "bird" }참고로, 빈 세트를 만들기 위해서는 {}가 아니라 set() 통해서 만들어야 합니다.
wrong_empty = {} # 이것은 딕셔너리입니다.
correct_empty = set() # 이것은 빈 세트입니다.세트에 데이터를 추가하기 위해서는 add() 메소드를 사용합니다. 반환값은 None이며 원본 세트가 변화됩니다.
empty = set()
empty.add('dog')세트에서 데이터를 삭제하기 위해서는 remove() 메소드를 사용합니다. 반환값은 None이며 원본 세트가 변화됩니다.
empty.remove('dog')딕셔너리
key-value 쌍으로 구성된 데이터 타입이며, key의 저장 순서가 유지됩니다. 단 key는 중복되면 안됩니다.
student = { "name": "손오공", "email": "son@email.com" }value에 접근하려면 key 값을 인덱스로 하여 접근합니다. 혹은 get 메소드를 통해서도 접근합니다.
두 방식의 차이점은 [ ] 방식은 키값이 없을 경우 에러를 발생시키지만, get 메소드는 없을 시 None을 반환합니다.
print(student['name']) # 손오공
print(student.get('name')) # 손오공get 방식의 경우, 예외적인 상황에서도 동작 가능하게 할 수 있으며, 값이 없을 경우를 대비해 default 값을 설정할 수 있습니다.
student.get('age', 22) # age 키 값이 없을 경우 에러가 아니라 22로 셋팅key를 통해 접근하여 그 value를 수정할수도 있습니다. 기존에 없는 key일 경우 알아서 딕셔너리에 추가됩니다.
student['name'] = '김은하'
student['address'] = '서울시'
print(student) # { 'name': '김은하', 'email': 'son@email.com', 'address': '서울시' }key와 value 값 삭제를 위해서는 del 연산자를 통해 삭제합니다.
del(student['email'])
print(student) # { 'name': '김은하', 'address': '서울시' }딕셔너리의 update 메소드를 통해 없는 key-value를 추가할 수도 있습니다.
student.update({ "age": 23 })딕셔너리 역시 dict() 함수를 통해 형변환하여 딕셔너리를 생성합니다.
첫번째, 빈 {}의 경우 위에서 살펴봤듯이 빈 딕셔너리로 해석합니다.
empty = {}두번째, dict()를 통해 역시 빈 딕셔너리를 만들 수 있습니다.
empty = dict()세번째, dict()의 파라미터로 key와 value를 설정해 딕셔너리에 추가할 수 있습니다.
my_dict= dict(host='127.0.0.1', port=3306)
print(my_dict) # { host: '127.0.0.1', port: 3306 }네번째, 리스트안에 튜플이 있는 형태를 dict로 바꿨을 때의 경우입니다.
my_dict = dict([
('host', '128.0.1.125'),
('port', 8080)
])
print(my_dict) # { 'host: '128.0.1.125', 'port': 8080 }key, value의 타입 제한에 대해 알아보면, value는 어떤 타입이든 가능하나, key는 hash 가능한 타입만 가능합니다.
key의 타입 예시로는 int, float, str, bool, tuple 등이 있습니다.
my_dict = {
1: 'haha',
2: 'hoho',
False: ['10','20','30']
(10,20): ['40','50','60']
}딕셔너리에서 key와 value 값을 뽑아내기 위한 함수 몇가지가 있습니다.
첫번째, keys() 메소드는 key로 구성된 iterable 객체를 리턴합니다. 주로 여기서는 list 형변환을 통해 [ ] 형태로 뽑아냅니다.
print(my_dict.keys()) # dict_keys([1, 2, False, (10, 20)])
print(list(my_dict.keys())) # [1, 2, False, (10, 20)]두번째, values() 메소드는 values로 구성된 iterable 객체를 리턴합니다. 주로 여기서도 list 형변환을 통해 [ ] 형태로 뽑아냅니다.
print(my_dict.values())
# dict_values(['haha', 'hoho', ['10', '20', '30'], ['40', '50', '60']])
print(list(my_dict.values()))
# ['haha', 'hoho', ['10', '20', '30'], ['40', '50', '60']]세번째, items() 메소드는 (key, value) 튜플들로 구성된 iterable 객체를 리턴합니다.
여기서도 list 형변환 통해 [ ] 형태로 뽑아냅니다.
print(list(my_dict.items()))
# [(1, 'haha'), (2, 'hoho'), (False, ['10','20','30']), ((10, 20), ['40','50','60']]