아래 표에 여섯 명의 이름, 전화번호, 나이, 키, 출생지 정보가 담겨 있다.
| 이름 | 전화번호 | 나이 | 키 | 출생지 |
|---|---|---|---|---|
| 김강현 | 010-1234-5678 | 20 | 172.3 | 제주 |
| 황현 | 02-9871-1234 | 19 | 163.5 | 서울 |
| 남세원 | 010-3456-7891 | 21 | 156.7 | 경기 |
| 최흥선 | 070-4321-1111 | 21 | 187.2 | 부산 |
| 김현선 | 010-3333-8888 | 22 | 164.6 | 광주 |
| 함중아 | 010-7654-2345 | 18 | 178.3 | 강원 |
예를 들어 김강현, 최흥선 등의 전화번호를 알고 싶으면 이름 칸에서 김강현과 최흥선이 위치한 행을 찾아 전화번호를 확인하면 된다. 하지만 만약에 여섯 명이 아니라 수천, 수만명의 정보를 담겨 있다면 특정인의 전화번호, 나이, 키, 출생지 등을 확인하는 일이 매우 어려워진다. 반면에 컴퓨터는 이런 일을 매우 빠르고 정확하게 처리한다.
그런데 컴퓨터가 정보를 처리하도록 하려면 먼저 위 표의 내용을 하나의 값으로 저장해야 한다. 예를 들어, 아래 김강현의 데이터를 저장하는 것처럼 이름, 전화번호, 나이, 키, 출생지 각각을 하나의 변수에 저장할 수 있다.
kgh_name = '김강현'
kgh_phone = '010-1234-5678'
kgh_age = 20
kgh_height = 172.3
kgh_birthplace = '제주'그런데 이렇게 하면 저장해야 하는 사람의 수가 조금만 늘어나도 데이터를 제대로 관리할 수 없게 된다. 이런 경우에는 여러 개의 값을 하나로 묶어 처리하는 모음 자료형이 활용된다.
모음 자료형은 아래 질문에 대해 적절한 답변을 제공한다.
표에 언급된 여섯 명의 이름으로 구성된 목록을 하나의 값으로 다룰 수 있을까?
이름과 전화번호를 하나의 쌍으로 묶어서 전화번호부를 만든 다음에 이름을 입력하면 전화번호를 확인하는 프로그램을 작성할 수 있을까?
5.1파이썬 내장 자료 구조¶
아래 그림은 여러 개의 값을 하나의 값으로 묶어 처리할 수 있도록 도와주는 네 개의 내장 자료 구조built-in data structure를 표현한다. 여기서 내장built-in이라 파이썬이 기본으로 제공한다는 의미다. 반면에 자료 구조data structure는 여러 개의 값으로 구성된 보다 복잡한 대상을 가리키는 값이다. 즉 리스트, 튜플, 사전, 집합 또한 하나의 값이다.

5.1.1모음 자료형 대 스칼라 자료형¶
리스트, 튜플, 사전, 집합은 각자 고유의 방식으로 여러 개의 값을 모아서 하나의 값으로 다룬다.
모음 자료형의 값에 포함된 항목의 수는 일반적으로 len() 함수를 이용하여 확인할 수 있다.
여러 개의 값을 모아 항목으로 포함한다는 의미에서 이들을 모음 자료형이라 부르며 경우에 따라 컬렉션collection, 컨테이너container 등으로도 불린다. 반면에 정수, 부동소수점, 불리언 등은 하나의 값으로만 구성되었다는 의미에서 스칼라scalar 자료형이라 부른다.
5.1.2모음 자료형 구분¶
파이썬에서 모음 자료형은 크게 두 가지 기준으로 나눌 수 있다.
항목의 순서와 중복 허용 여부
순차 자료형sequence type: 항목의 순서를 유지하며 중복을 허용한다. 흔히 시퀀스sequence라고도 한다.
비순차 자료형non-sequence type: 항목의 순서를 고려하지 않으며 중복된 항목은 자동으로 제거된다.
항목 변경 가능 여부
가변 자료형mutable type: 항목의 추가, 삭제, 변경이 가능하다.
불변 자료형immutable type: 생성된 값은 변경할 수 없다.
언급된 기중으로 파이썬 주요 자료형의 특징을 구분하면 다음과 같다.
리스트: 순서를 가지며 중복을 허용하는 순차 자료형이자, 항목을 자유롭게 수정할 수 있는 가변 자료형이다.
튜플: 리스트와 마찬가지로 순차 자료형이지만, 항목을 변경할 수 없는 불변 자료형이다.
사전과 집합: 항목의 순서를 고려하지 않는 비순차 자료형이며, 항목을 수정할 수 있는 가변 자료형이다.
문자열도 여러 개의 문자로 구성된 모음 자료형으로 간주하기도 한다. 그리고 문자열에 포함된 문자들의 순서가 중요하고 동일 문자를 반복해서 사용해도 되기에 문자열은 순차 자료형이며, 동시에 불변 자료형으로 분류된다.
앞으로 리스트, 튜플, 사전을 차례대로 보다 상세히 소개할 것이다. 이유는 데이터 과학에서 널리 사용되는 어레이array와 데이터프레임dataframe의 구조와 기능을 이해하기 위해 필요한 기초 지식을 이 세 자료형이 제공하기 때문이다.
여기서는 먼저 리스트를 소개한다.
5.2리스트¶
리스트는 대괄호 []로 항목들의 목록을 감싸고, 각각의 항목은 쉼표 ,로 구분한다.
예를 들어 앞서 개인 정보를 담은 표에 포함된 이름으로 구성된 리스트를
가리키는 변수 name_list는 다음과 같이 선언한다.
name_list = ['김강현', '황현', '남세원', '최흥선', '김현선', '함중아']그리고 아래 one2five 변수는 1부터 5까지의 정수로 구성된 리스트를 가리킨다.
one2five = [1, 2, 3, 4, 5]리스트 항목의 자료형
리스트의 항목이 반드시 동일한 자료형을 가질 필요는 없으며, 서로 다른 자료형의 항목이 사용될 수도 있다. 예를 들어 아래 리스트는 김강현과 황현의 이름, 전화번호, 나이, 키, 출생지로 구성된 리스트를 정의한다. 전화번호가 문자열로 지정되었음에 주의한다.
kgh = ['김강현', '010-1234-5678', 20, 172.5, '제주']whang = ['황현', '02-9871-1234', 19, 163.5, '서울']즉, 리스트의 자료형은 포함된 항목과 아무 상관없이 그냥 list 다.
type(kgh)listtype(one2five)list빈 리스트
빈 리스트는 아무것도 포함하지 않는 리스트를 의미한다. 다음 두 가지 방식으로 빈 리스트를 선언할 수 있다.
방법 1: 대괄호 활용
empty_list = []방법 2:
list()함수 활용
empty_list = list()중첩 리스트
임의의 값이 리스트의 항목으로 사용될 수 있다. 따라서 리스트가 다른 리스트의 항목으로 허용된다. 아래 코드는 김강현과 황현 두 사람의 정보로 구성된 길이가 2인 리트스를 정의한다.
kgh_whang = [kgh, whang] # 김강현, 황현 두 사람 정보확인하면 리스트의 리스트, 즉 중첩 리스트가 된다.
kgh_whang[['김강현', '010-1234-5678', 20, 172.3, '제주'],
['황현', '02-9871-1234', 19, 163.5, '서울']]kgh_whang이 가리키는 리스트에 포함된 항목의 개수, 리스트의 길이는 2다.
len(kgh_whang)2자료형은 여전히 list 다.
type(kgh_whang)list반면에 kgh와 whang 두 변수가 가리키는 리스트의 길이는 5다.
즉, 중첩 리스트의 길이는 항목으로 사용된 리스트의 길이와 무관하다.
len(kgh)5len(whang)5아래 코드에서 info_list는 나머지 4명의 정보도 항목으로 포함하는 (중첩) 리스트를 가리킨다.
namgung = ['남궁수현', '010-3456-7891', 21, 156.7, '경기']
choihs = ['최흥선', '070-4321-1111', 21, 187.2, '부산']
sjkim = ['김선주', '010-3333-8888', 22, 164.6, '광주']
ja = ['함중아', '010-7654-2345', 18, 178.3, '강원']info_list = [kgh, whang, namgung, choihs, sjkim, ja]
info_list[['김강현', '010-1234-5678', 20, 172.5, '제주'],
['황현', '02-9871-1234', 19, 163.5, '서울'],
['남궁수현', '010-3456-7891', 21, 156.7, '경기'],
['최흥선', '070-4321-1111', 21, 187.2, '부산'],
['김선주', '010-3333-8888', 22, 164.6, '광주'],
['함중아', '010-7654-2345', 18, 178.3, '강원']]info_list 변수가 가리키는 리스트의 길이는 6이다.
len(info_list)6리스트는 시퀀스!
리스트는 시퀀스 자료형이기에 항목의 순서가 다르거나 특정 항목의 개수가 다르면 서로 다른 리스트로 간주된다.
순서가 다른 경우:
one2five는 1부터 5까지의 순서로 되어 있기에 5부터 1까지로 구성된 리스트와 다르다고 간주된다.
one2five != [5, 4, 3, 2, 1]True특정 항목의 개수가 다른 경우:
name_list에는 김강현이 한 번 사용되었기에 두 번 사용된 리스트와는 다른 리스트로 간주된다.
name_list != ['김강현', '김강현', '황현', '남세원', '최흥선', '김현선', '함중아']True5.3리스트 인덱싱¶
리스트 인덱싱은 정수 인덱스가 가리키는 위치의 항목을 확인하거나 수정할 때 사용한다.
예를 들어 김강현의 정보를 담은 리스트 kgh 에서 이름은 0번 인덱스에 위치한다.
print(kgh)['김강현', '010-1234-5678', 20, 172.3, '제주']
kgh[0]'김강현'김강현의 전화번호는 1번 인덱스에 위치한다.
kgh[1]'010-1234-5678'-1, -2, -3 등 음수 인덱스는 리스트 오른쪽에서부터 위치를 찾는다. 따라서 김강현의 출생지는 -1번 인덱스로 확인한다.
kgh[-1]'제주'-1번 인덱스는 리스트의 길이에서 1을 뺀 인덱스와 동일한 위치를 가리킨다. 즉, 다음이 성립한다.
kgh_last_index = len(kgh) - 1
kgh[kgh_last_index] == kgh[-1]True김강현의 키는 리스트의 오른쪽 끝에서 두 번째 항목이기에 -2번 인덱스로 확인된다.
kgh[-2]172.3리스트는 항목을 수정할 수 있는 가변 자료형이며 인덱싱을 이용하여 특정 위치의 항목을 수정할 수 있다. 예를 들어 아래 코드는 김강현의 출생지를 제주가 아닌 제주시로 수정한다.
kgh[kgh_last_index] = '제주시' # kgh의 마지막 인덱스에 '제주시'를 수정물론 -1번 인덱스도 사용할 수 있다.
kgh[-1] = '제주시'김강현의 출생지 정보가 제주시로 변경되었다.
kgh['김강현', '010-1234-5678', 20, 172.3, '제주시']인덱스 허용 범위
리스트 인덱싱에 사용되는 인덱스는 리스트의 길이에 의해 결정된다.
예를 들어 김강현의 정보를 담은 리스트의 길이가 5이기 때문에
-5부터 4까지의 정수만 인덱싱에 허용된다.
지정된 범위를 벗어난 인덱스를 사용하면
지정된 인덱스의 범위를 벗어났다(list index out of range)는
설명과 함께 IndexError오류가 발생한다.
kgh[5]---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[35], line 1
----> 1 kgh[5]
IndexError: list index out of range5.4리스트 슬라이싱¶
슬라이싱은 두 개의 인덱스로 지정된 구간에 포함된 항목들을 확인하거나 수정할 때 사용한다. 경우에 따라 몇 걸음씩 건너뛸지 지정하기도 한다.
시작 인덱스: 슬라이싱 구간 시작 인덱스. 생략되면 0을 기본값으로 사용.
끝 인덱스: 슬라이싱 구간 끝 인덱스. 이 인덱스 이전 인덱스까지 항목 확인. 생략되면 오른쪽 끝까지를 의미함.
보폭: 구간 시작부터 몇 개씩 건너뛰며 항목을 확인할 것인지 결정. 보폭이 1이면 생략 가능.
예를 들어 김강현의 이름, 전화번호, 나이, 키는 0번부터 3번 인덱스에 위치하기에
대괄호 안에 0:4를 입력하여 0번 인덱스부터 4번 인덱스 이전인 3번 인덱스의 항목으로
구성된 리스트가 확인된다.
kgh[0:4]['김강현', '010-1234-5678', 20, 172.3]보폭이 1인 경우와 동일하다.
kgh[0:4:1]['김강현', '010-1234-5678', 20, 172.3]시작 인덱스가 0이면 생략해도 된다. 단 콜론은 그대로 둬야 한다.
kgh[:4]['김강현', '010-1234-5678', 20, 172.3]슬라이싱의 결과는 항상 리스트이다. 구간의 크기가 1이라 해도 그렇다. 예를 들어 아래 코드는 김강현의 전화번호로만 구성되어 길이가 1인 리스트가 확인된다.
kgh[1:2]['010-1234-5678']보폭을 1보다 크게 지정하면 지정된 보폭만큼 건너 뛰며 항목을 확인한 결과를 리스트로 보여준다. 예를 들어 김강현의 전화번오와 키를 함께 확인하려면 1번과 3번 인덱스를 확인해야 하기에 다음과 같이 보폭을 2로 지정한다.
kgh[1:4:2]['010-1234-5678', 172.3]이름과 키를 확인하려면 0번부터 끝까지를 구간으로 하면서 보폭을 3으로 지정한다.
kgh[0::3]['김강현', 172.3]시작 인덱스를 생략해도 된다.
kgh[::3]['김강현', 172.3]리스트 전체를 대상으로 슬라이싱하려면 아래와 같이 한다.
kgh[:]['김강현', '010-1234-5678', 20, 172.3, '제주시']또는
kgh[::] # kgh 전체 대상 슬라이싱. 스텝은 1이 기본값.['김강현', '010-1234-5678', 20, 172.3, '제주시']슬라이싱에 리스트의 크기를 벗어나는 인덱스를 사용하더라도 오류가 발생하지 않는다. 대신 허용되는 인덱스의 구간에 대해서만 슬라이싱이 적용된다. 아래 코드는 5번 인덱스부터 9번 인덱스까지 확인하려 하지만 해당 인덱스의 위치를 찾을 수 없기에 빈 리스트를 생성한다.
kgh[5:10][]아래 코드는 0번 인덱스부터 7번 인덱스까지 확인하려 하지만 결국엔 4번 인덱스까지만 확인하게 된다.
kgh[0:8]['김강현', '010-1234-5678', 20, 172.3, '제주시']보폭을 2 이상으로 지정해도 허용된 인덱스의 범위를 벗어난 인덱스는 무시된다.
kgh[0:8:2]['김강현', 20, '제주시']역순 슬라이싱
슬라이싱은 기본적으로 작은 인덱스에서 큰 인덱스 방향으로 확인한다. 음수 보폭을 지정하면 큰 인덱스에서 작은 인덱스 방향으로 움직이는 역순 슬라이싱이 실행된다.
예를 들어, 아래 코드는 보폭이 -1이고, 시작 인덱스와 끝 인덱스를 생략하면 문자열 전체를 역순으로 확인한다. 이 기법은 리스트 항목들의 순서를 뒤집는 데에 자주 활용된다.
kgh[:: -1]['제주시', 172.3, 20, '010-1234-5678', '김강현']보폭이 음수이면서 시작 인덱스가 끝 인덱스보다 작으면 빈 리스트가 생성된다.
kgh[2:5:-1][]시작 인덱스가 끝 인덱스보다 크면 구간의 오른쪽부터 항목을 확인한다 점만 다를 뿐이다. 아래 코드는 -2번 인덱스부터 왼쪽으로 두 걸음씩 건너 뛰며 슬라이싱을 진행한다. 역순 인덱싱에서 끝 인덱스가 생략되면 왼쪽 끝까지를 의미힌다.
kgh[-2::-2][172.3, '010-1234-5678']구간 수정
슬라이싱을 이용하여 리스트의 지정된 구간을 다른 리스트로 대체할 수 있다. 아래 코드는 김강현의 키와 출생지를 동시에 수정한다.
kgh[3:] = [172.5, '제주']
kgh['김강현', '010-1234-5678', 20, 172.5, '제주']슬라이싱 구간의 크기와 새롭게 대체하는 리스트의 크기가 다를 수 있다. 설명을 위해 다음 리스트를 이용한다.
a2f = ['a', 'b', 'c', 'd', 'e', 'f']소문자 c와 d를 대문자 C와 D로 수정하고 곧바로 대문자 Z를 추가하고자 한다면 2번, 3번 인덱스 구간을 슬라이싱하면서 동시에 값을 다음과 같이 3개 지정하면 된다.
a2f[2:4] = ['C', 'D', 'Z']
a2f['a', 'b', 'C', 'D', 'Z', 'e', 'f']만약 보폭을 2이상으로 지정하면 슬라이싱된 항목의 개수와 새롭게 지정된 리스트의 길이가 같아야 한다. 아래 코드는 홀수 인덱스에 위치한 항목을 모두 해당 인덱스로 대체한다.
a2f[1::2] = [1, 3, 5]
a2f['a', 1, 'C', 3, 'Z', 5, 'f']보폭이 1이 아닌 경우
대체 리스트의 길이가 슬라이싱된 항목의 개수와 다르면 두 리스트의 크기가 다르다는 설명과 함께 ValueError가 발생한다.
아래 코드는 슬라이싱된 항목은 2개이지만 길이가 3인 리스트를 대체 리스트로 지정하기에 오류가 발생한다.
a2f[:3:2] = ['X', 'Y', 'Z']---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[55], line 1
----> 1 a2f[:3:2] = ['X', 'Y', 'Z']
ValueError: attempt to assign sequence of size 3 to extended slice of size 25.5중첩 리스트의 인덱싱/슬라이싱/반복문¶
중첩 리스트는 리스트의 항목 또한 리스트이기 때문에
항목의 항목을 확인/추출/변경 하려면 인덱싱, 슬라이싱, for 반복문을
연속적으로 또는중첩해서 적용해야 한다.
인덱싱 연속 적용
예를 들어 김강현의 이름은 info_list의 첫째 항목 리스트의 첫째 항목이다.
info_list[['김강현', '010-1234-5678', 20, 172.5, '제주'],
['황현', '02-9871-1234', 19, 163.5, '서울'],
['남세원', '010-3456-7891', 21, 156.7, '경기'],
['최흥선', '070-4321-1111', 21, 187.2, '부산'],
['김현선', '010-3333-8888', 22, 164.6, '광주'],
['함중아', '010-7654-2345', 18, 178.3, '강원']]김강현의 이름은 info_list의 0번 인덱스에 포함되어 있다.
따라서 먼저 김강현의 정보를 담은 리스트를 인덱싱으로 추출한다.
kgh_name = info_list[0]
kgh_name['김강현', '010-1234-5678', 20, 172.5, '제주']다시 0번 인덱스를 적용하면 김강현의 이름이 확인된다.
kgh_name[0]'김강현'인덱싱을 연속 적용하는 과정을 다음과 같이 줄여서 하나의 표현식으로 나타낼 수 있다.
info_list[0][0]'김강현'아래 코드는 유사한 방식으로 황현의 이름과 나이를 확인한다.
hwang_name = info_list[1][0]
hwang_age = info_list[1][2]
print(f"{hwang_name}의 나이: {hwang_age}세")황현의 나이: 19세
슬라이싱과 인덱싱 연속 적용
황현, 최흥선, 함중아만 대상으로 나이를 확인하려 한다.
그런데 세 사람의 정보는 info_list가 가리키는 리스트의 1번, 3번, 5번 인덱스에 위치한다.
info_list[1::2][['황현', '02-9871-1234', 19, 163.5, '서울'],
['최흥선', '070-4321-1111', 21, 187.2, '부산'],
['함중아', '010-7654-2345', 18, 178.3, '강원']]아래 코드는 세 사람의 정보를 대상으로 for 반복문과 인덱싱을 인덱싱을 적용하면
세 사람의 나이 정보를 추출한다.
for person in info_list[1::2]:
print(f"{person[0]}:\t{person[2]}세")황현: 19세
최흥선: 21세
함중아: 18세
인덱싱과 슬라이싱 연속 적용
아래 코드는 4번 인덱스에 위치한 김현선의 이름, 전화번호, 나이를 확인한다.
info_list[4][:3]['김현선', '010-3333-8888', 22]중첩 반복문 활용
예제 1
중첩 for 반복문을 사용하여 6명 각자의 정보를 일일이 나열할 수 있다.
for person in info_list: # 6명 모두를 대상으로 반복
for item in person:
print(item) # 한 사람의 모든 정보 출력. 항목들 사이는 탭으로 구분
print() # 사람들 사이의 구분을 위해 줄 바꿈김강현
010-1234-5678
20
172.5
제주
황현
02-9871-1234
19
163.5
서울
남세원
010-3456-7891
21
156.7
경기
최흥선
070-4321-1111
21
187.2
부산
김현선
010-3333-8888
22
164.6
광주
함중아
010-7654-2345
18
178.3
강원
print() 함수의 end='\n' 키워드 옵션을 변경하여 한 사람의 정보를 한 줄에 출력할 수 있다.
for person in info_list:
for item in person:
print(item, end='\t') # 한 사람의 정보는 탭으로 구분
print() 김강현 010-1234-5678 20 172.5 제주
황현 02-9871-1234 19 163.5 서울
남세원 010-3456-7891 21 156.7 경기
최흥선 070-4321-1111 21 187.2 부산
김현선 010-3333-8888 22 164.6 광주
함중아 010-7654-2345 18 178.3 강원
예제 2
아래 코드는 나이가 21살인 사람의 정보만 출력한다.
for person in info_list:
if 21 == person[2]: # 나이가 21살인 사람만 선택
for item in person:
print(item, end='\t')
print()남세원 010-3456-7891 21 156.7 경기
최흥선 070-4321-1111 21 187.2 부산
예제 3
이름에 “현” 자가 포함된 사람의 정보만 출력하러면 다음과 같이 한다.
for person in info_list:
if '현' in person[0]: # 이름에 "현" 자가 포함된 사람만 선택
for item in person:
print(item, end='\t')
print()김강현 010-1234-5678 20 172.5 제주
황현 02-9871-1234 19 163.5 서울
김현선 010-3333-8888 22 164.6 광주
"현"으로 끝나는 경우만 다루려면 endswith() 문자열 메서드를 이용한다.
for person in info_list:
if person[0].endswith('현'): # 이름이 "현" 자로 끝나는 사람만 선택
for item in person:
print(item, end='\t')
print()김강현 010-1234-5678 20 172.5 제주
황현 02-9871-1234 19 163.5 서울
startswith() 문자열 메서드를 이용하여 김씨 성만 추출할 수도 있다.
for person in info_list:
if person[0].startswith('김'): # 김씨 성 정보만 선택
for item in person:
print(item, end='\t')
print()김강현 010-1234-5678 20 172.5 제주
김현선 010-3333-8888 22 164.6 광주
5.6리스트 메서드¶
모음 자료형의 기본 용도는 여러 개의 값을 모아 하나의 값으로 다루면서 필요에 따라 유용한 항목을 탐색하고 추출하는 기능이다. 리스트 자료형에 대해서만 사용할 수 있는 함수들인 리스트 메서드가 다양하게 제공된다.
문자열 자료형과는 달리 리스트는 변경을 허용하는 가변 자료형이기에 항목의 탐색뿐만 아니라 리스트 자체를 수정하는 항목의 추가와 삭제, 항목들의 정렬을 수행하는 메서드 또한 제공된다. 간단한 예제를 이용하여 리스트의 아래 표에 언급된 주요 리스트 메서드의 기능을 살펴 본다.
Table 1:리스트 주요 메서드
기능 | 메서드 | 설명 |
|---|---|---|
복사 |
| 리스트의 사본 반환 |
탐색 |
| 리스트에서 지정된 항목이 등장한 횟수 반환 |
| 지정된 항목이 처음 사용된 인덱스 반환 | |
추가/삽입/확장 |
| 리스트 끝에 항목 추가. 반환값은 |
| 지정된 인덱스에 항목 삽입. 반환값은 | |
| 다른 리스트를 연결하여 확장. 반환값은 | |
삭제 |
| 지정된 인덱스의 항목 삭제 후 반환. |
| 가장 왼쪽에 위치한 지정된 항목 삭제. 반환값은 | |
정렬 |
| 리스트의 항목을 크기 순으로 정렬. 반환값은 |
| 리스트의 항목들 순서 뒤집기. 반환값은 |
copy() 메서드
리스트는 가변 자료형이기에 인덱싱, 슬라이싱을 포함하여 이어서 소개하는 많은 메서드에 의해
수정될 수 있다.
따라서 경우에 따라 주어진 원본 리스트는 전혀 건드리지 않으면서 리스트를 이용할 필요가 있다.
그럴 때 copy() 메서드로 사본을 만들어 이용한다.
예를 들어, 아래 코드는 변수 x가 가리키는 리스트의 사본을 만들어 변수 y에 할당한다.
그 다음에 y가 가리키는 리스트의 0번 인덱스 항목을 수정하지만 변수 x가
가리키는 리스트는 전혀 변하지 않는다.
x = [1, 2, 3]
y = x.copy()
y[0] = 10 # 0번 인데스 항목 수정
print("y:", y) # 수정됨
print("x:", x) # 불변y: [10, 2, 3]
x: [1, 2, 3]
아래 그림은 두 변수 x와 y가 선언된 순간의 메모리 상태를 보여준다.
x와 y가 동일하게 생겼지만 각각 서로 다른 리스트를 가리킨다.

아래 그림은 y가 가리키는 리스트의 첫째 항목이 10으로 업데이트된 이후의 메모리 상태를 보여주며,
변수 x가 가리키는 리스트는 전혀 수정되지 않는다.

반면에 아래 코드에서처럼 사본을 만들지 않으면 리스트 원본이 함께 수정된다.
이유는 x와 y가 동일한 리스트를 가리키기 때문이다.
x = [1, 2, 3]
y = x
y[0] = 10 # 0번 인데스 항목 수정
print("x:", x)
print("y:", y)x: [10, 2, 3]
y: [10, 2, 3]
아래 그림은 두 변수 x와 y가 선언된 순간의 메모리 상태를 보여준다.
x와 y가 동일한 리스트를 가리킨다.

아래 그림은 y가 가리키는 리스트의 첫째 항목이 10으로 업데이트되면
x가 동일한 리스트를 가리키기에 0번 인덱스 항목이 똑같이 10이 된다.

count() 메서드
인자로 지정된 항목이 리스트에 몇 번 사용되었는지를 반환한다.
예를 들어, [1, 2, 3, 1, 2]에 1과 2는 두 번, 3은 한 번 사용된다.
oneTwoThree = [1, 2, 3, 1, 2]oneTwoThree.count(1)2oneTwoThree.count(2)2oneTwoThree.count(3)1항목이 아니면 0을 반환한다.
oneTwoThree.count(4)0index() 메서드
인자로 지정된 항목이 위치한 인덱스를 반환한다.
항목이 여러 번 사용된 경우 가장 왼쪽에 위치한 곳의 인덱스를 선택한다.
예를 [1, 2, 3, 1, 2, 3]에서 2가 두 번 사용되었지만
1번 인덱스에서 가장 먼저 사용된다.
oneTwoThree.index(2)1반면에 3은 2번 인덱스에서 처음 사용된다.
oneTwoThree.index(3)2리스트의 항목으로 존재하지 않으면 ValueError 오류가 발생한다.
oneTwoThree.index(5)---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[79], line 1
----> 1 oneTwoThree.index(5)
ValueError: 5 is not in list참고로 문자열의 경우와는 다르게 리스트는 find() 메서드를 제공하지 않는다.
append() 메서드
리스트의 오른쪽 끝에 항목을 추가한다.
반환값은 None이다.
아래 코드는 oneTwoThree가 가리키는 리스트에 3을 추가한다.
oneTwoThree.append(3)반면에 oneTwoThree가 가리키는 리스트 자체가 수정되었다.
oneTwoThree[1, 2, 3, 1, 2, 3]아래 for 반복문은 1, 2, 3을 한 번씩 더 추가한다.
for i in range(1, 4):
oneTwoThree.append(i)oneTwoThree[1, 2, 3, 1, 2, 3, 1, 2, 3]insert() 메서드
insert() 메서드는 인덱스를 이용하여 특정 위치에 항목을 삽입한다.
반환값은 None이다.
항목이 삽입되면 원래 그 위치를 포함해서 오른쪽에 위치했던 항목들은
모두 한 칸씩 오른쪽으로 이동된다.
아래 코드는 1번 인덱스 자리에 2를 삽입하여 1부터 4까지의 정수로 구성된 리스트를 완성한다.
one2four = [1, 3, 4]
one2four.insert(1, 2) # 1번 인덱스에 2 삽입one2four[1, 2, 3, 4]아래 for 반복문은 4, 3, 2, 1을 차례대로 0번 인덱스에 추가한다.
for i in range(4, 0, -1):
one2four.insert(0, i)one2four[1, 2, 3, 4, 1, 2, 3, 4]extend() 메서드
append() 메서드는 기존의 리스트 오를쪽 끝에 하나의 항목을 추가한다.
반면에 extend() 메서드는 기존 리스트의 오른쪽 끝에 인자로 지정된 리스트를 연결한다.
반환값은 None이다.
아래 코드는 one2four가 가리키는 리스트에
[1, 2, 3, 4]를 연결한다.
one2four.extend([1, 2, 3, 4])one2four[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]참고로 + 연산자는 리스트 두개를 이어붙여 완전히 새로운 리스트를 생성한다.
예를 들어 아래 코드는 one2four가 가리키는 리스트와 [1, 2, 3, 4]를 연결한 새로운 리스트를 생성한다.
one2four + [1, 2, 3, 4][1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]one2four가 가리키는 리스트는 수정되지 않았다.
one2four[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]pop() 메서드
pop() 메서드는 지정된 인덱스의 항목을 반환하는 동시에 리스트에서 삭제한다.
설명을 위해 one2four 변수를 계속 활용한다.
아래 코드는 3번 인덱스에 위치한 정수 4를 리스트에서 삭제하면서 동시에 반환한다.
four_index3 = one2four.pop(3)pop() 함수는 삭제된 항목을 반환한다.
four_index343번 인덱스의 항목인 4가 one2four에서 삭제되었다.
삭제된 항목의 오른쪽에 위치한 항목은 한 칸씩 왼쪽으로 이동한다.
one2four[1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4]one2four를 원래대로 되돌려 놓기 위해 insert() 메서드를 이용한다.
one2four.insert(3, four_index3)one2four[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]pop() 메서드의 인자를 지정하지 않으면 리스트의 마지막 항목이 삭제된 후 반환된다.
one2four.pop()4마지막 항목이기에 이번엔 append() 메서드로 원래대로 되돌린다.
one2four.append(4)one2four[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]remove() 메서드
remove() 메서드는 리스트에서 지정된 항목을 삭제할 뿐 해당 항목을 반환하진 않는다.
즉 None을 반환한다.
지정된 항목이 리스트에 여러 번 포함되었을 경우 가장 왼편에 위치한 항목을 삭제한다.
아래 코드는 1을 삭제한다.
one2four.remove(1)0번 인덱스에 있었던 1만 삭제되었다.
one2four[2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]삭제할 항목이 없으면 ValueError 오류가 발생한다.
one2four.remove(0)---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[102], line 1
----> 1 one2four.remove(0)
ValueError: list.remove(x): x not in listfor 반복문을 이용하여 2, 3, 4를 차례로 삭제하자.
for num in [2, 3, 4]:
one2four.remove(num)one2four[1, 2, 3, 4, 1, 2, 3, 4]sort() 메서드
리스트의 항목을 크기 순으로 정렬하는 방식으로 리스트를 수정한다.
즉, 리스트 자체가 수정되며, 반환값은 None이다.
예를 들어 아래 코드는 one2four의 항목을 크기 순으로 정렬한다.
one2four.sort()one2four[1, 1, 2, 2, 3, 3, 4, 4]reverse=True 키워드 인자를 지정하면 내림차순으로 정렬한다.
one2four.sort(reverse=True)one2four[4, 4, 3, 3, 2, 2, 1, 1]reverse() 메서드
단순히 리스트에 포함된 항목들의 순서를 뒤집는다.
반환값은 None이다.
설명을 위해 아래 리스트를 이용한다.
acbgf = ['a', 'c', 'b', 'g', 'f']아래 코드는 acbgf에 포함된 순서를 뒤집는다.
acbgf.reverse()acbgf['f', 'g', 'b', 'c', 'a']reverse() 메서드를 한 번 더 적용하면 원래 순서대로 돌아온다.
acbgf.reverse()acbgf['a', 'c', 'b', 'g', 'f']5.7리스트 조건제시법¶
수학에서 0과 10사이에 있는 홀수들의 제곱을 원소로 갖는 집합을 조건제시법으로 표현하면 다음과 같다.
0과 10 사이에 있는 홀수들의 제곱을 항목으로 갖는 리스트를 for 반복문으로 구현해 보자.
zero2ten_odd = []
for x in range(11):
if x%2 == 1:
zero2ten_odd.append(x**2)
zero2ten_odd[1, 9, 25, 49, 81]조건제시법을 이용하여 보다 간단하게 리스트를 생성할 수 있다.
zero2ten_odd = [x**2 for x in range(11) if x%2 == 1]
zero2ten_odd[1, 9, 25, 49, 81]위 두 코드를 비교하면 조건제시법의 작동원리를 이해할 수 있을 것이다.