Py) 기초 - 객체(리스트)

Py) 기초 - 객체(리스트)

파이썬 기반 데이터분석을 위하여 파이썬 기본 객체중 하나인 리스트(list)에 대해 알아본다.


개요

리스트(list)는 파이썬에서 가장 기본이 되는 객체이며 보통 2개 이상의 원소를 묶을 때 리스트를 사용한다. 향후 딕셔너리(dictionary)의 value, NumPy의 배열(Array), Pandas 객체 생성 및 색인 등 다양하게 사용된다.

  • 생성
    대괄호를 사용하여 생성하며 그 원소는 쉼표로 구분함. 리스트의 원소는 숫자, 문자 뿐만 아니라 리스트 또는 기타 객체도 될 수 있다.
  • 색인
    인덱스는 0부터 시작하며 리스트 객체 뒤에 대괄호를 사용하여 내부의 원소에 접근할 수 있음. 문자열을 다루는 것 처럼 단일 또는 연속된 인덱스에 대응하는 원소를 추출 가능하나 이산수열 인덱스에 대응하는 원소는 한 번에 추출이 불가하고 이 경우 반복문과 조건문을 사용해야 한다.
    색인에 사용하는 인덱스는 정수만 가능하며 음수의 경우 마지막 원소를 기준으로 상대적으로 얼마나 뒤에 위치하는지를 의미한다.
  • 조작
    원소 추가/제거/치환 등 다양한 작업이 가능. 복수 원소의 일괄연산은 불가하며 필요시 반복문 등 제어문을 활용해야 한다.

실습

생성 및 인덱싱

다음과 같이 대괄호를 사용하여 리스트를 생성할 수 있으며 해당 리스트에는 원소(element)가 1, 2, 3이 있다.

1
2
[1, 2, 3]
## [1, 2, 3]

다음은 원소 100, 200, 300으로 구성된 리스트를 할당 연산자(assignment operator)를 사용하여 “aa” 객체(object)에 리스트를 할당하고 다음 줄에서 “aa” 객체를 확인하는 코드이다.

1
2
3
aa = [100, 200, 300]
aa
## [100, 200, 300]

리스트 내부의 단일 또는 복수개의 원소에 접근하려면 대괄호와 인덱스를 같이 써야 한다. 인덱스는 0 부터 시작하며 연속범위를 지정할 때에는 콜론을 사용한다. 그리고 연속범위 지정시 인덱스 번호가 0부터 시작한다면 콜론 왼쪽의 0은 생략할 수 있으며 콜론의 오른쪽을 생략하는 경우는 마지막 인덱스를 지정하는 것과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
aa[0]
## 100

aa[1]
## 200

aa[2]
## 300

aa[0:2]
## [100, 200]

aa[:2]
## [100, 200]

상기 코드의 결과가 예상한 것과 조금 다를 수 있는데 연속범위를 지정하는 경우 콜론 오른쪽에 지정한 인덱스 번호에 해당하는 원소까지 접근할 수 없다. 그래서 초심자는 이 부분에서 실수를 많이 하며 코드 작성에 유의해야 한다. 만약 콜론을 사용하여 모든 원소에 접근하고자 한다면 다음과 같이 코드를 작성할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
aa[0:3]
## [100, 200, 300]

aa[0:]
## [100, 200, 300]

aa[:3]
## [100, 200, 300]

aa[:]
## [100, 200, 300]

파이썬의 경우 마지막 원소에 접근하는 트릭과 같은 코드가 있는데 해당 코드는 다음과 같다.

1
2
3
4
5
aa[-1]
## 300

aa[-2:]
## [200, 300]

상기 코드에서 -1은 마지막 원소. 즉, 뒤에서 첫 번째 원소를 지칭하며 -2는 뒤에서 두 번째 원소를 지칭한다. 그래서 상기 코드처럼 객체의 원소 개수에 대한 정보가 없어도 손쉽게 가장 마지막 원소를 기준으로 코드를 작성할 수 있다.

치환 및 조작

일반적으로 객체의 원소에 접근하는 코드를 작성할 수 있으면 해당 원소를 다른 값 또는 객체로 치환하는 코드 또한 작성할 수 있다. 다음의 코드는 “aa” 객체의 첫 번째 원소를 -1로 치환하는 코드이다.

1
2
3
aa[0] = -1
aa
## [-1, 200, 300]

이번에는 두 번째 원소에 500을 더해보도록 한다.

1
2
aa[1] = aa[1] + 500 
aa

상기 코드를 보면 어떤 특수한 함수를 사용하는 것이 아니라 두 번째 원소에 접근하는 코드와 할당 연산자를 활용하고 있다. 즉, 두 번째 원소를 들어내어 거기에 500을 더하고 다시 해당 자리에 끼워넣는 방식으로 코드를 작성하고 있다. 이 코드를 잘 기억해야 한다. 앞으로 작성하는 파이썬 코드는 이러한 방식으로 값을 치환하는 경우가 많기 때문에 코드 구조(또는 패턴)를 기억하면 훨씬 수월하게 코드를 작성할 수 있을 것이다.

리스트의 경우 산술연산자를 사용하여 리스트를 합치거나 원소 복제를 할 수 있다.

1
2
3
4
5
6
7
8
9
10
list1 = [22, 33, 44]
list2 = [55, 66, 77]
list1 + list2
## [22, 33, 44, 55, 66, 77]

list1 + [999]
## [22, 33, 44, 999]

list1 * 3
## [22, 33, 44, 22, 33, 44, 22, 33, 44]

리스트를 더하면 리스트를 이어붙일 수 있고 특정 리스트를 곱하면 해당 리스트를 곱한 숫자(자연수)만큼의 리스트를 서로 이어붙인 결과와 같은 것을 알 수 있다.

메서드의 사용

리스트 객체를 조작하기 위해 사용할 수 있는 메서드(method)는 다음과 같다.

‘append’, ‘clear’, ‘copy’, ‘count’, ‘extend’, ‘index’, ‘insert’, ‘pop’, ‘remove’, ‘reverse’, ‘sort’

해당 메서드는 dir() 함수로 확인할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
dir(aa)
## ['__add__',
## '__class__',
## '__class_getitem__',
## '__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']

뭔가 잔뜩 출력되어서 당황할 수 있다. 그럴 때는 다음의 코드와 같이 리스트 내포(컴프리핸션, comprehension)를 사용하여 언더바로 시작하는 원소를 걸러낼 수 있으나 상세한 내용은 다른 게시글에서 다루고자 한다.

1
2
3
4
5
6
7
8
9
10
11
12
[m for m in dir(aa) if m[0] != "_"]
## ['append',
## 'clear',
## 'copy',
## 'count',
## 'extend',
## 'index',
## 'insert',
## 'pop',
## 'remove',
## 'reverse',
## 'sort']

이제 메서드가 어떤 것이 있는지 확인했으니 직접 써보도록 하자.

1
2
3
aa.extend([999])
aa
## [100, 200, 300, 999]

.extend() 메서드는 + 연산자를 사용하여 리스트를 이어붙이는 것과 똑같은 결과를 보여준다. 그래서 이 연산을 수행하는 경우 보통 .extend() 메서드 보다는 +를 사용하는 경우가 많다.

다음은 이와 비슷한 .append() 메서드이다. .extend() 메서드는 숫자나 문자의 입력이 들어오면 에러가 나기 때문에 보통 리스트를 입력으로 집어넣는 반면 .append() 메서드는 숫자나 문자 그 자체를 입력으로 할 수 있다. (단, 하나의 원소만 입력가능)

1
2
3
4
bb = [1, 2]
bb.append(3)
bb
## [1, 2, 3]

다음 코드의 실행 결과는 중첩된(nested) 리스트임을 알 수 있다. 그래서 .extend() 메서드와 혼동하여 오사용 하는 일이 없도록 주의해야 한다.

1
2
3
4
cc = [5, 6]
cc.append([7, 8])
cc
## [5, 6, [7, 8]]

이번에는 특정 원소의 인덱스 번호를 확인하는 .index() 메서드를 알아보자.

1
2
3
dd = [666, 777, 888]
dd.index(777)
## 1

상기 코드는 666, 777, 888을 원소로 하는 “dd”객체가 있을 때 원소 777의 인덱스 번호를 확인하는 코드이다. 그리고 만약 .index() 메서드의 사용 대상 리스트 객체 내에 없는 원소를 입력할 경우 다음과 같이 에러가 발생한다.

1
2
3
4
5
6
7
dd.index(0)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_15652\661537774.py in <module>
----> 1 dd.index(0)

ValueError: 0 is not in list

상기 에러메세지를 해석해보면, 리스트 안에 원소 0이 없기 때문에 발생했다는 것을 알 수 있다.

나머지 메서드는 활용도가 상대적으로 떨어지기에 별도로 다루지 않는다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×