파이썬 기반 데이터분석을 위하여 파이썬 기본 객체중 하나인 리스트(list)에 대해 알아본다.
개요
리스트(list)는 파이썬에서 가장 기본이 되는 객체이며 보통 2개 이상의 원소를 묶을 때 리스트를 사용한다. 향후 딕셔너리(dictionary)의 value, NumPy의 배열(Array), Pandas 객체 생성 및 색인 등 다양하게 사용된다.
- 생성
대괄호를 사용하여 생성하며 그 원소는 쉼표로 구분함. 리스트의 원소는 숫자, 문자 뿐만 아니라 리스트 또는 기타 객체도 될 수 있다.
- 색인
인덱스는 0부터 시작하며 리스트 객체 뒤에 대괄호를 사용하여 내부의 원소에 접근할 수 있음. 문자열을 다루는 것 처럼 단일 또는 연속된 인덱스에 대응하는 원소를 추출 가능하나 이산수열 인덱스에 대응하는 원소는 한 번에 추출이 불가하고 이 경우 반복문과 조건문을 사용해야 한다.
색인에 사용하는 인덱스는 정수만 가능하며 음수의 경우 마지막 원소를 기준으로 상대적으로 얼마나 뒤에 위치하는지를 의미한다.
- 조작
원소 추가/제거/치환 등 다양한 작업이 가능. 복수 원소의 일괄연산은 불가하며 필요시 반복문 등 제어문을 활용해야 한다.
실습
생성 및 인덱싱
다음과 같이 대괄호를 사용하여 리스트를 생성할 수 있으며 해당 리스트에는 원소(element)가 1, 2, 3이 있다.
1 | [1, 2, 3] |
다음은 원소 100, 200, 300으로 구성된 리스트를 할당 연산자(assignment operator)를 사용하여 “aa” 객체(object)에 리스트를 할당하고 다음 줄에서 “aa” 객체를 확인하는 코드이다.
1 | aa = [100, 200, 300] |
리스트 내부의 단일 또는 복수개의 원소에 접근하려면 대괄호와 인덱스를 같이 써야 한다. 인덱스는 0 부터 시작하며 연속범위를 지정할 때에는 콜론을 사용한다. 그리고 연속범위 지정시 인덱스 번호가 0부터 시작한다면 콜론 왼쪽의 0은 생략할 수 있으며 콜론의 오른쪽을 생략하는 경우는 마지막 인덱스를 지정하는 것과 같다.
1 | aa[0] |
상기 코드의 결과가 예상한 것과 조금 다를 수 있는데 연속범위를 지정하는 경우 콜론 오른쪽에 지정한 인덱스 번호에 해당하는 원소까지 접근할 수 없다. 그래서 초심자는 이 부분에서 실수를 많이 하며 코드 작성에 유의해야 한다. 만약 콜론을 사용하여 모든 원소에 접근하고자 한다면 다음과 같이 코드를 작성할 수 있다.
1 | aa[0:3] |
파이썬의 경우 마지막 원소에 접근하는 트릭과 같은 코드가 있는데 해당 코드는 다음과 같다.
1 | aa[-1] |
상기 코드에서 -1은 마지막 원소. 즉, 뒤에서 첫 번째 원소를 지칭하며 -2는 뒤에서 두 번째 원소를 지칭한다. 그래서 상기 코드처럼 객체의 원소 개수에 대한 정보가 없어도 손쉽게 가장 마지막 원소를 기준으로 코드를 작성할 수 있다.
치환 및 조작
일반적으로 객체의 원소에 접근하는 코드를 작성할 수 있으면 해당 원소를 다른 값 또는 객체로 치환하는 코드 또한 작성할 수 있다. 다음의 코드는 “aa” 객체의 첫 번째 원소를 -1로 치환하는 코드이다.
1 | aa[0] = -1 |
이번에는 두 번째 원소에 500을 더해보도록 한다.
1 | aa[1] = aa[1] + 500 |
상기 코드를 보면 어떤 특수한 함수를 사용하는 것이 아니라 두 번째 원소에 접근하는 코드와 할당 연산자를 활용하고 있다. 즉, 두 번째 원소를 들어내어 거기에 500을 더하고 다시 해당 자리에 끼워넣는 방식으로 코드를 작성하고 있다. 이 코드를 잘 기억해야 한다. 앞으로 작성하는 파이썬 코드는 이러한 방식으로 값을 치환하는 경우가 많기 때문에 코드 구조(또는 패턴)를 기억하면 훨씬 수월하게 코드를 작성할 수 있을 것이다.
리스트의 경우 산술연산자를 사용하여 리스트를 합치거나 원소 복제를 할 수 있다.
1 | list1 = [22, 33, 44] |
리스트를 더하면 리스트를 이어붙일 수 있고 특정 리스트를 곱하면 해당 리스트를 곱한 숫자(자연수)만큼의 리스트를 서로 이어붙인 결과와 같은 것을 알 수 있다.
메서드의 사용
리스트 객체를 조작하기 위해 사용할 수 있는 메서드(method)는 다음과 같다.
‘append’, ‘clear’, ‘copy’, ‘count’, ‘extend’, ‘index’, ‘insert’, ‘pop’, ‘remove’, ‘reverse’, ‘sort’
해당 메서드는 dir() 함수로 확인할 수 있다.
1 | dir(aa) |
뭔가 잔뜩 출력되어서 당황할 수 있다. 그럴 때는 다음의 코드와 같이 리스트 내포(컴프리핸션, comprehension)를 사용하여 언더바로 시작하는 원소를 걸러낼 수 있으나 상세한 내용은 다른 게시글에서 다루고자 한다.
1 | [m for m in dir(aa) if m[0] != "_"] |
이제 메서드가 어떤 것이 있는지 확인했으니 직접 써보도록 하자.
1 | aa.extend([999]) |
.extend() 메서드는 +
연산자를 사용하여 리스트를 이어붙이는 것과 똑같은 결과를 보여준다. 그래서 이 연산을 수행하는 경우 보통 .extend() 메서드 보다는 +
를 사용하는 경우가 많다.
다음은 이와 비슷한 .append() 메서드이다. .extend() 메서드는 숫자나 문자의 입력이 들어오면 에러가 나기 때문에 보통 리스트를 입력으로 집어넣는 반면 .append() 메서드는 숫자나 문자 그 자체를 입력으로 할 수 있다. (단, 하나의 원소만 입력가능)
1 | bb = [1, 2] |
다음 코드의 실행 결과는 중첩된(nested) 리스트임을 알 수 있다. 그래서 .extend() 메서드와 혼동하여 오사용 하는 일이 없도록 주의해야 한다.
1 | cc = [5, 6] |
이번에는 특정 원소의 인덱스 번호를 확인하는 .index() 메서드를 알아보자.
1 | dd = [666, 777, 888] |
상기 코드는 666, 777, 888을 원소로 하는 “dd”객체가 있을 때 원소 777의 인덱스 번호를 확인하는 코드이다. 그리고 만약 .index() 메서드의 사용 대상 리스트 객체 내에 없는 원소를 입력할 경우 다음과 같이 에러가 발생한다.
1 | dd.index(0) |
상기 에러메세지를 해석해보면, 리스트 안에 원소 0이 없기 때문에 발생했다는 것을 알 수 있다.
나머지 메서드는 활용도가 상대적으로 떨어지기에 별도로 다루지 않는다.