..

Search

13) 리스트 타입

리스트 타입


리스트(list)

파이썬에서는 기본 데이터 타입인 숫자형 타입, 불리언 타입, 문자열 타입과는 별도로 이들로 구성되는 다양한 컨테이너 형태의 데이터 구조를 제공합니다. 그 중에서도 가장 많이 사용되는 것이 바로 리스트(list) 타입입니다.

 

리스트(list)는 간단히 순서대로 늘어선 박스로 이해할 수 있습니다. 각 박스에는 다양한 타입의 데이터를 저장할 수 있으며, 이 박스들을 통틀어서 리스트라고 부르게 됩니다.

 

list

 

파이썬에서 리스트는 다음과 같은 특징을 가집니다.

 

1. 리스트에 저장되는 요소가 모두 같은 타입일 필요는 없습니다.

2. 리스트에는 요소들이 순서대로 저장되며, 각 요소는 0부터 시작하는 인덱스(index)를 사용하여 접근할 수 있습니다.

3. 리스트는 그 값을 변경할 수 있습니다. (mutable type)

 

아무런 요소도 저장하고 있지 않은 리스트를 빈 리스트(empty list)라고 부르며, 파이썬에서는 []로 표현할 수 있습니다.

 

이와 같은 데이터 타입을 다른 프로그래밍 언어에서는 배열(array)이라고도 부르지만, 파이썬에서는 리스트(list)라는 용어만을 사용합니다.

리스트 선언하기

파이썬에서 리스트는 대괄호([])로 감싸서 선언할 수 있으며, 리스트 안의 요소(element)들은 쉼표(,)로 구분합니다.

문법

리스트명 = [요소1, 요소2, 요소3, ...]

 

다음 예제는 4개의 요소를 가지는 리스트를 선언하고, 해당 리스트의 모든 요소를 출력하는 예제입니다.

예제

primes = [2, 3, 5, 7]  

 

for p in primes:

    print(p)  

 

print(len(primes))

코딩연습 ▶

실행 결과

2
3
5
7
4

 

위의 예제처럼 리스트는 같은 타입의 데이터뿐만 아니라 서로 다른 타입의 데이터도 함께 저장할 수 있으며, for 문을 사용하면 저장된 모든 요소에 손쉽게 접근할 수 있습니다.

 

또한, 파이썬 내장 함수인 len() 함수를 사용하면 리스트의 길이, 즉 리스트에 저장된 모든 요소의 개수를 손쉽게 알 수 있습니다.


리스트 요소 선택하기

for 문을 사용하면 리스트의 모든 요소에 순차적으로 접근할 수 있습니다. 하지만 리스트의 특정 요소에만 접근하고 싶을 때에는 0부터 시작하는 인덱스(index)를 사용해야만 합니다.

 

리스트의 첫 번째 요소는 0, 두 번째 요소는 1, 세 번째 요소는 각각 2의 인덱스를 가지며 이처럼 리스트의 각 요소는 저장될 때 순서대로 1씩 증가되는 인덱스를 자동으로 부여받습니다. 또한, 문자열과 마찬가지로 음의 인덱스를 지원하며, 음의 인덱스는 리스트의 마지막 요소를 -1로 놓고 역순으로 증가됩니다.

예제

primes = [2, 3, 5, 7]  

 

print(primes[0])

print(primes[-1])

print(primes[1] + primes[3])  

 

# print(primes[5])

코딩연습 ▶

실행 결과

2
7
10

 

위의 예제에서 primes[-1]과 primes[3]은 똑같이 리스트의 마지막 요소인 7을 가리키고 있습니다. 리스트의 모든 요소는 이처럼 양의 인덱스와 음의 인덱스의 두 가지 방법으로 접근할 수 있습니다.

 

이때 주석 처리된 7번 라인처럼 리스트의 총 길이를 벗어난 올바르지 않은 인덱스를 사용하게 되면, IndexError가 발생하며 프로그램은 강제 종료됩니다. 따라서 리스트를 사용할 때는 언제나 리스트의 길이와 인덱스에 충분한 주의를 기울여야 합니다.


리스트 자르기

리스트를 다루다보면 리스트의 일부분만을 선택하거나 리스트의 일부 요소들만을 수정해야 할 경우가 생깁니다. 이러한 경우 손쉽게 처리할 수 있도록 문자열과 마찬가지로 리스트에서도 슬라이싱(slicing)을 지원하고 있습니다.

예제

list1 = [1, 2, 3, 4, 5]  

 

print(list1[3])

print(list1[1:3])

print(list1[:3])

print(list1[3:])

print(list1)

코딩연습 ▶

실행 결과

4
[2, 3]
[1, 2, 3]
[4, 5]
[1, 2, 3, 4, 5]

 

위 예제의 4번 라인처럼 콜론(:)기호를 사용하면 리스트의 일부분만을 자를 수 있으며, 이때 콜론의 앞쪽에 위치한 인덱스부터 콜론의 뒤쪽에 위치한 인덱스 바로 앞까지의 요소를 모두 반환합니다.

 

이때 유의할 점은 콜론의 앞쪽에 위치한 인덱스는 곧바로 시작 인덱스가 되지만, 콜론의 뒤쪽에 위치한 인덱스는 해당 인덱스에서 1을 뺀 인덱스가 마지막 인덱스가 된다는 점입니다.

 

하지만 7번 라인의 실행 결과에서 확인할 수 있듯이 리스트 자르기는 원본 리스트에는 전혀 영향을 미치지 않으며, 해당 부분에 해당하는 새로운 리스트를 생성하여 반환해 주는 것입니다.


리스트 복사하기

예제

list1 = [1, 2, 3, 4, 5]  

 

copy = list1

copy.append(6)  

 

print(copy)

print(list1)

코딩연습 ▶

실행 결과

[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]

 

위의 예제에서는 대입 연산자(=)를 사용하여 리스트를 그대로 변수에 대입함으로써 리스트를 복사하고자 합니다. 그리고나서 4번 라인에서 복사된 리스트에 6을 추가합니다.

하지만 6번과 7번 라인의 실행 결과에서 추가한 6이라는 요소가 복사된 리스트뿐만 아니라 원본 리스트에도 추가되었음을 확인할 수 있습니다.

 

이처럼 단순히 리스트명을 변수에 대입하는 것은 리스트를 복사하는 것이 아니라 원본 리스트의 메모리 주소만을 넘겨주는 것입니다. 즉, 3번 라인에 의해 리스트명 list1과 변수명 copy는 같은 리스트를 가리키게 된 것입니다.

 

따라서 리스트의 복사본을 제대로 만들고 싶다면 다음과 같이 리스트 슬라이싱을 이용하여 리스트를 복사해야 합니다.

예제

list1 = [1, 2, 3, 4, 5]  

 

copy = list1[:]

copy.append(6)  

 

print(copy)

print(list1)

코딩연습 ▶

실행 결과

[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]

 

위 예제의 3번 라인에서 사용된 list1[:]은 리스트 list1의 모든 요소를 선택하여 자르는 구문입니다. 이렇게 잘린 리스트는 원본 리스트와는 별도의 리스트로 반환되기때문에 6번과 7번 라인을 통해 리스트가 제대로 복사되었음을 확인할 수 있습니다.


리스트끼리의 연산

파이썬에서는 리스트끼리 더하거나 리스트에 숫자를 곱할 수도 있습니다.

리스트끼리의 더하기(+) 연산은 두 리스트를 서로 연결시켜주며, 리스트와 정수의 곱하기(*) 연산은 해당 리스트의 모든 요소들을 정수배만큼 반복해서 연결해 줍니다.

예제

list1 = [1, 2, 3]

list2 = list((4, 5, 6))

 

print(list1 + list2)

print(list1 * 3)  

 

list1.extend(list2)

print(list1)

코딩연습 ▶

실행 결과

[1, 2, 3, 4, 5, 6]
[1, 2, 3, 1, 2, 3, 1, 2, 3]
[1, 2, 3, 4, 5, 6]

 

위 예제의 7번 라인과 같이 extend() 함수를 사용하면 더하기(+) 연산과 마찬가지로 하나의 리스트에 다른 리스트를 연결할 수 있습니다. 단, 리스트끼리의 더하기(+) 연산은 원본 리스트에는 전혀 영향을 미치지 않지만, extend() 함수는 원본 리스트 그 자체를 변경하는 점이 다릅니다.

 

또한, 위 예제의 1번과 2번 라인처럼 파이썬에서 리스트는 대괄호를 사용하거나 list() 함수를 사용해서 선언할 수 있습니다. 이때 list() 함수의 인수로는 순환할 수 있는 객체(iterable object)만을 사용할 수 있습니다.


리스트에 요소 추가하거나 제거하기

append() 함수는 전달된 인수를 해당 리스트의 마지막 요소로 추가하고, remove() 함수는 전달된 인수를 해당 리스트에서 찾아 제거합니다.

예제

list1 = [1, 2, 3, 4, 5]  

 

list1.append(2)

print(list1)  

 

list1.remove(3)

print(list1)  

 

list1.remove(2)

print(list1)

코딩연습 ▶

실행 결과

[1, 2, 3, 4, 5, 2]
[1, 2, 4, 5, 2]
[1, 4, 5, 2

 

만약 remove() 함수에 인수로 전달한 요소가 해당 리스트에 두 개 이상 존재할 경우에는 위 예제의 9번 라인처럼 인덱스가 가장 낮은 요소 하나만을 삭제하게 됩니다.


리스트에 요소 삽입하거나 꺼내기

insert() 함수는 해당 리스트의 지정된 인덱스에 전달된 인수를 요소로 삽입하며, pop() 함수는 전달받은 인덱스에 위치한 요소를 리스트에서 추출하여 반환합니다.

예제

list1 = [1, 2, 3, 4, 5]  

 

list1.insert(3, 9)

print(list1)  

 

list1.pop(4)

print(list1)

코딩연습 ▶

실행 결과

[1, 2, 3, 9, 4, 5]
[1, 2, 3, 9, 5]

 

insert() 함수는 첫 번째 인수로 요소를 삽입할 인덱스를 전달받고, 두 번째 인수로 삽입할 요소를 전달받습니다.


리스트 뒤집거나 정렬하기

reverse() 함수는 리스트의 모든 요소를 역순으로 뒤집어서 반환하며, sort() 함수는 리스트의 모든 요소를 순서대로 정렬해줍니다.

예제

list1 = [5, 2, 4, 1, 3]

list2 = [5, 2, 4, 1, 3]  

 

list1.reverse()

print(list1)  

 

list1.sort()

print(list1)  

 

print(sorted(list2))

print(list2)

코딩연습 ▶

실행 결과

[3, 1, 4, 2, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[5, 2, 4, 1, 3]

 

위 예제의 10번 라인과 같이 파이썬의 내장 함수인 sorted() 함수를 사용해도 리스트를 정렬할 수 있습니다.

이때 리스트 함수인 sort() 함수는 원본 리스트 그 자체를 정렬하여 변경하지만, 파이썬 내장 함수인 sorted() 함수는 원본 리스트는 변경하지 않고 정렬된 새로운 리스트를 반환해 줍니다.


중첩 리스트

파이썬에서는 리스트의 요소로 또 다른 리스트를 추가할 수 있습니다.

이때 중첩된 안쪽 리스트의 특정 요소의 인덱스는 두 개의 대괄호([][])를 사용하여 표시할 수 있습니다.

예제

matrix = [[1, 2, 3], ["하나", "둘", "셋"]]  

 

print(matrix[0])

print(matrix[0][0])

print(matrix[1][2])

코딩연습 ▶

실행 결과

[1, 2, 3]
1

 

위 예제의 4번 라인처럼 중첩 리스트에서 첫 번째 인덱스는 바깥쪽 리스트의 인덱스로 인식되며, 두 번째 인덱스는 안쪽 리스트의 인덱스로 인식됩니다. 따라서 5번 라인은 바깥쪽 리스트의 두 번째 요소인 안쪽 리스트에서 또 다시 세 번째 요소를 선택하라는 의미가 됩니다.

 

이와 같은 방법을 사용하여 리스트를 몇 번이고 중첩시킬 수 있지만, 현실적으로 이해하기 쉽도록 2번 이상의 중첩은 잘 사용하지 않습니다.


연습문제