Python

4. 자료형(data types)- 리스트(list)

김아다만티움 2021. 9. 11. 14:48

*본 게시물은 21-2학기 연세대학교 일반대학원 온라인데이터수집과분석(이상엽 교수님) 수업 내용을 정리한 것입니다.

 

대망의 리스트입니다.

  리스트는 자연어 처리를 하는 사람이라면 정말 모를 수가 없을 정도로 유명하고, 또 저같은 문과 쪼렙들(?)에게는 딕셔너리와 더불어 두려움의 대상으로 다가오는! 도대체가 [:-1]은 뭐고 [:]가 뭔지 눈물을 흘리게 만드는 자료형입니다... 리스트 겹괄호 쓰여지면 토크나이징도 제대로 안되는거 아시져 흑...

 

1. 리스트의 정의

  아무튼 리스트는 '여러 개의 데이터, 값을 저장하기 위해' 사용되는 데이터 타입입니다. 저장되는 데이터들은 타입이 달라도 상관 없습니다. 리스트 선언은 '[]'(각괄호; square brackets)로 선언하며, 데이터들은 쉼표로 구분됩니다. 또한 리스트는 sequential한 데이터입니다. 즉 줄줄이 들어가는 연속된 데이터로 간주됩니다. 

1
= ['python'15]  #a라는 변수에 여러 자료형이 들어간 리스트 저장
cs

 

2. 인덱싱(indexing)과 슬라이싱(slicing)

(1) 인덱싱(indexing)  

  리스트 다루기의 양대산맥은 인덱싱(indexing)과 슬라이싱(slicing)입니다.

  먼저 인덱싱은 리스트에 저장된 하나의 원소에 접근할 수 있는 방법입니다. 접근은 데이터가 가진 인덱스를 통해 이루어지는데, 인덱스는 앞에서도 시작할 수 있고, 뒤에서도 시작할 수 있습니다.

  앞에서 시작할 경우 인덱스 번호는 0부터 시작하게 되며 뒤에서 시작할 경우 -1, -2 순으로 내려갑니다. 특히 인덱스 -1의 경우 리스트 안 원소 개수가 몇 개인지 몰라도 제일 마지막 원소에 접근이 가능하기 때문에 굉장히 널리 쓰이는 인덱스 번호입니다.

'python' 1 5
0 1 2
-3 -2 -1

인덱싱 형태는 리스트[인덱스 번호]입니다. 다음과 같이 인덱싱을 할 수 있습니다.

1
2
3
4
5
6
7
= ['python'15]  #a라는 변수에 여러 자료형이 들어간 리스트 저장

a[0]  # 'python'
a[1]  # 1
a[2]  # 5

a[-1# 5
a[-2# 1
a[-3# 'python'
cs

또한 인덱싱을 가지고서도 type()함수나 기타 함수를 사용할 수도 있습니다 :D

1
2
3
4
= ['python'15]  #a라는 변수에 여러 자료형이 들어간 리스트 저장
 
type(a[0])  # str
print(a[0])  # python ; print함수를 사용하면 작은 따옴표는 나오지 않습니다.
cs

 

 

(2) 슬라이싱(slicing)

  인덱싱은 원소 하나하나에 접근이 가능했습니다. 다만 인덱싱할 원소의 갯수가 아주아주 많다면? 매우 비효율적인 일이 발생할 것입니다. 가령 a[1] ....a[10] 처럼 말이죠. 여러 원소를 꺼내기 위해서는 따라서 슬라이싱이 필요합니다.

 

  슬라이싱은 범위로 지정됩니다. 형태는 리스트[인덱스 번호x:인덱스번호y]로 표시됩니다.

  앞에서부터 슬라이싱을 할 경우 인덱스 번호x '이상'부터 인덱스 번호y '미만'까지의 원소들을 리스트로 리턴합니다. 

1
2
3
4
5
= ['python'12'java'345]  #a라는 변수에 여러 자료형이 들어간 리스트 저장
 
a[0:4]  # 인덱스 번호 0 이상 인덱스 번호 4 미만인 ['python', 1, 2, 'java'] 리턴
a[1:6]  # 인덱스 번호 1 이상 인덱스 번호 6 미만인 [1, 2, 'java', 3, 4] 
 
cs

인덱스 번호가 꼭 2개 들어가지 않아도 괜찮습니다. 위와 마찬가지로 리스트[인덱스 번호x:]는 인덱스 번호x '이상'부터 끝까지, 리스트[:인덱스 번호y]는 앞에서부터 인덱스 번호y '미만'까지의 원소들을 리스트로 리턴합니다. 

1
2
3
4
5
6
= ['python'12'java'345]  #a라는 변수에 여러 자료형이 들어간 리스트 저장
 
a[1:] #인덱스 번호 1 이상부터 끝까지인 [1, 2, 'java', 3, 4, 5] 리턴
a[3:] #인덱스 번호 3 이상부터 끝까지인 ['java', 3, 4, 5] 리턴
a[:6#인덱스 번호 6 미만까지인 ['python', 1, 2, 'java', 3, 4] 리턴
a[:4#인덱스 번호 4 미만까지인 ['python', 1, 2, 'java']
cs

 

  그렇다면 슬라이싱을 뒤에서부터 하면 어떻게 될까요? 우선 인덱스 번호가 2개 등장하는 슬라이싱을 해보겠습니다.

1
2
3
4
5
= ['python'12'java'345]  #a라는 변수에 여러 자료형이 들어간 리스트 저장
 
a[-7:-1#인덱스 번호 -7부터 -1미만인 인덱스 번호 -2까지 ['python', 1, 2, 'java', 3, 4] 리턴
a[-6:-1#인덱스 번호 -6부터 -1미만인 인덱스 번호 -2까지 [1, 2, 'java', 3, 4] 리턴
a[-5:-2#인덱스 번호 -5부터 -2미만인 인덱스 번호 -3까지 [2, 'java', 3] 
cs

음수라서 조금 헷갈리지만 그래도 앞에서부터 하는 슬라이싱과 원리가 똑같습니다. 앞에 나오는 인덱스 번호 이상 뒤에 나오는 인덱스 번호 미만의 원소들이 리스트로 리턴됩니다.

그렇다면 인덱스번호가 하나 나오는 슬라이싱은 어떨까요? 음수라서 조금 헷갈릴 뿐 역시 작동 원리가 똑같습니다. 

1
2
3
4
5
6
= ['python'12'java'345]  #a라는 변수에 여러 자료형이 들어간 리스트 저장
 
a[:-2# 인덱스 번호 -2 미만까지인 인덱스 번호 -3까지의 ['python', 1, 2, 'java', 3] 리턴
a[:-1# 인덱스 번호 -1 미만까지인 인덱스 번호 -2까지의 ['python', 1, 2, 'java', 3, 4] 리턴
a[-6:] # 인덱스 번호 -6부터 끝까지인 [1, 2, 'java', 3, 4, 5] 리턴
a[-2:] # 인덱스 번호 -2부터 끝까지인 [4, 5] 
cs

그렇다면 인덱스 번호 하나 없이 콜론 하나만 나오면 어떻게 될까요?

1
2
3
4
= ['python'12'java'345]  #a라는 변수에 여러 자료형이 들어간 리스트 저장
 
a[:] # 리스트 전체 리턴: ['python', 1, 2, 'java', 3, 4, 5]
# ['python', 1, 2, 'java', 3, 4, 5]
cs

리스트 전체가 리턴이 됩니다. 리스트 전체 리턴의 경우 단순하게 리스트가 저장된 변수 하나를 타이핑해서 얻을 수 있으니 굳이 사용할 필요가 없겠죠...?

 

 

3. 리스트를 변형(modifying)하는 메서드(method)/함수(function)들

리스트는 변경 가능(mutable)한 데이터 타입입니다. 이에 따라 리스트에 저장된 원소들을 바꾸거나, 없애거나 추가로 끼워넣거나 하는 모든 것들이 가능합니다. 가령 다음과 같이 원소 교체, 리스트 더하기 작업들이 가능합니다.

1
2
3
4
5
6
7
8
9
10
= [1,2,3,4# 이렇게 선언된 x라는 리스트에서
 
x[1= 'python' # 인덱스 번호 1을 가진 원소 1을 'python'으로 교체할 수 있습니다.
# 짜잔 [1, 'python', 3, 4] 
x[0:2= 100101 #또한 2개 이상의 원소를 바꾸는 것도 가능합니다.
# 짜잔 [100, 101, 3, 4]
 
#또한 리스트는 리스트끼리 더하는 것도 가능합니다.
= [6,7,8]
x+# [100, 101, 3, 4, 6, 7, 8]
cs

이외에도 더욱 다양한 작업들을 할 수 있는데, 다양한 작업들을 가능하게 만드는 것은 메서드와 함수입니다. 다음의 내용들이 소개될 예정입니다 :D

리스트=a

메서드(method) 일반 함수(common function)
a.append(원소값, [리,스,트]) min(a), max(a)
a.extend([리,스,트]) len(a)
a.remove(원소값) del a[인덱스변호]
a.index(원소값) sorted(a)
a.count(원소값)  
a.insert(인덱스번호, 원소값)  
a.sort()  

 

 

(1) 메서드(method): 변수.메서드() 형태

메서드는 특정 자료형하고만 사용되는 함수입니다. 다만 저는 아직 메서드에 대해 정확히 모르므로, 밑의 문단에서부터는 함수라고 하겠습니다.

여기서 다룰 함수는 리스트에서 사용되는 함수들입니다. 리스트 자료형과 어울려 쓸 수 있는 함수(메서드) 확인은 빌트인 함수 dir()을 통해 확인 가능합니다.  

1
2
3
4
5
6
7
8
9
10
11
12
13
= [1,2,3,4# 이렇게 선언된 x라는 리스트에서
 
dir(x) #x에 저장된 자료형에 쓸 수 있는 function들을 보여줌 
'''
'__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__',
 '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__',
 '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__',
 '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__',
 '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__',
 '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 
'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove',
 'reverse', 'sort'
'''
cs

언더바가 2개씩 붙은 function 들은 magic function이라 하여 일반인(?)들은 거어어어의 쓸 빈도가 적은 함수입니다. 이에 따라 list에 일반인이 ^^; 사용할 수 있는 함수는 append부터 sort 입니다. 지금부터는 append, extend, remove, index, count, insert, sort에 대해 살펴보겠습니다. 


  1) append

     append는 기존 리스트에 원소 '하나'를 끼워넣는 함수입니다. 이때 끼워넣는 원소는 숫자, 문자, 리스트 등 어떤 자료형이든 가능합니다. 

1
2
3
4
5
6
7
= [1,2,3,4# x 리스트에
x.append('추가된원소'#'추가된원소'라는 원소를 끼워넣으면?
# [1, 2, 3, 4, '추가된원소']
 
= [1,2,3,4# x 리스트에
x.append(5#를 하면?
# [1, 2, 3, 4, 5]
cs

또한 append의 인자에 리스트를 받게 되면, 기존 리스트에 인자로 받은 리스트를 끼워넣게 됩니다. 이 끼워 넣어진 리스트 속 리스트는 접근할 수 있는 인덱싱 및 슬라이싱이 가능해집니다.

1
2
3
4
5
6
= [1,2,3,4# x 리스트에
 
x.append([1,0])
# [1,2,3,4,[1,0]]
x[-1][0# x 리스트의 가장 마지막 원소인 [1,0]의 0번째 인덱스인 1이 나옴
#이는 그냥 리스트 [1,0][0] 과 똑같습니다. 
cs

 

  2) extend

     extend 역시 append와 비슷하나, exptend는 리스트를 인자로 받아 원소를 여러 개 추가할 수 있다는 점에서 다릅니다. 즉 append가 리스트를 인자로 받게 되면 리스트 통째로를 원소 하나로 추가하나, extend는 리스트를 인자로 받게 된다면 그 리스트 안의 원소들을 하나씩 꺼내서 기존 리스트에 원소 하나씩으로 추가합니다. 통으로 넣느냐 뜯어서 넣느냐의 차이가 발생합니다 ㅋㅋㅋ

1
2
3
4
5
6
7
8
= [1,2,3#z라는 리스트가 있을 때,
z.extend([4,5]) #extend에 리스트를 인자로 넣으면
# [1,2,3,4,5] #인자로 넣어진 리스트 속 원소들이 각각의 원소가 됩니다. 
 
#비교
= [1,2,3#z라는 리스트가 있을 때,
z.append([4,5])
# [1,2,3, [4,5]]로 통으로 들어갑니다. 
cs

 

  3) remove 

     remove는 말 그대로 인자로 넣은 원소 혹은 리스트의 인덱스에 있는 원소가 제거되는 함수입니다. 원소를 인자로 넣으면 그 원소 값과 일치하는 원소가, 리스트 인덱스를 인자로 넣으면 인덱스 번호에 해당하는 원소가 지워집니다.

1
2
3
4
5
6
7
8
= [1,2,3,4]  # k 라는 리스트가 있을 때
k.remove(3# 3과 일치하는 원소가 지워집니다.
# 짜잔 [1,2,4]
 
# remove는 리스트 인덱스로도 인자를 넣을 수 있습니다.
= [1,2,3,4]  # k 라는 리스트가 있을 때
k.remove(k[2]) #리스트 k의 인덱스를 인자로 넣으면
# 짜잔 2번 인덱스인 3이 지워져 [1,2,4]가 됩니다.
cs

그렇다면 리스트 안에 동일한 원소들이 있으면 어떻게 될까요? 앞에 있는 원소들부터 사라지게 됩니다.

1
2
3
= [1,2,3,4,1#동일한 값을 갖는 원소가 2개 이상 존재 시
k.remove(1#앞쪽에 있는 원소부터 사라집니다.
#앞에서부터 없어지므로 [2,3,4,1]
cs

 

  4) index

     index 함수는 특정 원소의 index 값을 받아오는 함수입니다. index 함수의 경우 리스트 안에 동일 원소가 있다고 해도 맨 처음 등장하는 원소만 나옵니다.

1
2
3
4
5
= [1,2,3'index메서드',3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3#라는 리스트가 있을 경우 ^^;
 
x.index('index메서드'#'index메서드' 원소의 인덱스를 구합니다.
# 'index메서드'의 인덱스 값은 3입니다.
x.index(3# 첫 번째 등장하는 3의 인덱스인 2밖에 나오지 않습니다.
cs

 

  5) count

     count 함수는 리스트 안에 특정 원소가 몇 개나 있는지 세는 함수입니다.  

1
2
= [1,2,3'index메서드',3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3#라는 리스트가 있을 경우 ^^;
x.count(3# 를 하여 3의 갯수를 구합니다. 총 28개네요.
cs

 

  6) insert: x.insert(인덱스 번호, 값)

     insert는 특정 인덱스 위치에 원소를 추가할 수 있는 함수입니다. 기존 인덱스의 '앞'에 원소를 추가하게 됩니다. '앞'이 중요한 이유는 뒤에서부터 인덱스를 세는 경우 때문입니다. 자연수 인덱스일 때는 insert가 인자로 받는 인덱스 번호가 새로 추가되는 값의 인덱스 번호가 되나, 음의 정수 인덱스일 때는 인자로 받는 인덱스 번호를 가진 원소의 '앞'에 오게 됩니다.

1
2
3
4
5
6
7
8
9
= [1,2,3'index메서드',4#이런 리스트가 있다고 가정할 때
 
x.insert(4,'insert메서드'# 인덱스 번호 4인 4 앞에 'insert메서드'를 삽입합니다. 
# 짜잔 [1, 2, 3, 'index메서드', 'insert메서드', 4]
 
#음의 정수 인덱스일 때
= [1,2,3'index메서드',4#이런 리스트가 있다고 가정할 때
x.insert(-2'insert메서드는어디로'# 인덱스 번호 -2 '앞'에 삽입합니다.
x  # 짜잔  [1, 2, 3, 'insert메서드는어디로', 'index메서드', 4]
cs

 

  7) sort()

     마지막으로 sort() 함수입니다. sort는 인자를 입력받지 않습니다. 해당 리스트의 원소를 기본적으로 '오름차순'으로 정렬해 줍니다. '내림차순'으로 정렬하고자 할 때는 ()안에 reverse=True 를 기입합니다.

다만 정렬하려면 데이터 타입이 동일해야 하며, sort()를 작동하는 순간 원소 순서가 바뀐 채로 리스트가 갱신됩니다(!!!!) 이를 방지하려면 일반 함수(common function)의 sorted()를 사용하면 됩니다. 뒤에 다루겠습니다.

1
2
3
x= [3,1,2,5'햇빛이''god'# 리스트 안에 서로 다른 데이터 타입을 가진 원소들이 섞여 있습니다.
x.sort()  # 이를 소트하면?
# 어림도 없지 에러 발생!: TypeError: '<' not supported between instances of 'str' and 'int'
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#데이터가 숫자형인 경우
x= [3,1,2,5# 숫자라는 단일 데이터 타입으로 구성된 리스트입니다. 
x.sort() #오름차순으로 정렬되고 x에 다시 저장됩니다. 
#[1, 2, 3, 5]
 
x= [3,1,2,5# 숫자라는 단일 데이터 타입으로 구성된 리스트입니다. 
x.sort(reverse=True#내림차순 정렬되고 x에 다시 저장됩니다.  
#[5, 3, 2, 1]
 
 
#데이터가 문자열인 경우
xx= ['bananas''lemon''apple''사과'#문자열이라는 단일 데이터 타입으로 구성된 리스트입니다.
xx.sort() #오름차순 정렬 후 xx에 다시 저장됩니다. 
xx # ['apple', 'bananas', 'lemon', '사과']
 
xx= ['bananas''lemon''apple''사과']
xx.sort(reverse=True# 내림차순 정렬 후 xx에 다시 저장됩니다.
xx # ['사과', 'lemon', 'bananas', 'apple']
cs

 

 

(2) 일반 함수(common functions): 함수() 형태

  일반 함수는 보편적으로 사용되는 함수들입니다. 리스트에 적용할 수 있는 함수들은 min(), max(), len(), 연산자 del x[index] 그리고 sorted()입니다. 차례로 살펴보겠습니다. 

 

  1) min(), max()

     이름에서 알 수 있듯이 리스트 안에서 최솟값, 최댓값을 보여주는 함수입니다. 아까 sort메서드와 같이 리스트 안에 데이터 타입이 모두 동일해야 사용할 수 있으며, 놀랍게도 문자열에도 min(), max() 적용이 가능합니다! 이는 컴퓨터가 문자열도 숫자의 연속으로 보고 처리하기 때문입니다 :D

1
2
3
4
5
6
7
8
9
# min(), max()를 사용하기 위해서는 일단 자료형이 같아야 합니다.
yy= ['a',1,3# 데이터 타입이 혼재되어 이습니다. 
min(yy) # TypeError: '<' not supported between instances of 'int' and 'str'
 
#숫자 리스트에서 min/ max는 너무나 예상이 가니...
#문자열에 대해서도 최소/최대 비교가 가능합니다.
= ['b','c','a'
min(s) # 'a'
max(s) # 'c'
cs

 

2) len()

     len()은 길이, 즉 원수 갯수를 리턴하는 함수입니다. 간단한 함수로 세상 쉽게 리스트 안 원소 갯수를 알 수 있습니다.

1
2
= [1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,3,5,6,6,6,3,3,3,111111
#사람이 일일이 세면 어려운 원소 갯수를
len(x) #함수를 작동하면 금방 27이라고 나옵니다 :D
cs

 

  3) 연산자 del x[index]

     연산자(operator)를 사용하여 원소를 지우는 함수입니다.

1
2
3
4
= ['b','c','a', ['d','e']] # 변수 s에 이러한 리스트를 저장합니다.
 
del s[0# 변수 s에 저장된 리스트에서 인덱스 번호 0에 해당하는 원소를 지우면
#['c', 'a', ['d', 'e']] #'b'가 삭제됩니다.
cs

 

  4) sorted()

     sorted()는 앞서 나온 메서드 sort()와 비슷하게 생겼으나, 인자로 변수를 받고 원소 순서를 바꾸어 저장하지 않는다는 점 에서 차이가 있습니다. 마찬가지로 데이터 타입은 동일해야 하며, 숫자나 문자열 모두 가능합니다. 

1
2
3
4
5
6
7
8
# 원소가 숫자인 리스트 정렬
ss= [1,2,3,777,54,3,42,1]
sorted(ss) # [1, 1, 2, 3, 3, 42, 54, 777] 라는 결과만 보여주며, 저장되지 않습니다.
 
#원소가 문자인 리스트 정렬
qq= ['a','viral','sensus']
sorted(qq) #기본 오름차순으로 정렬되며, 결과를 저장하지 . ['a', 'sensus', 'viral']
sorted(qq, reverse=True# reverse 옵션도 가능합니다! ['viral', 'sensus', 'a']
cs

 

 

 

 

ㅇㅇ