파이썬 기초 강좌 #8 리스트 (List)

16 분 소요

이번 강좌에서는 파이썬에서 아주 중요한 데이터 스트럭쳐 중에 하나인 리스트에 대해서 공부해보겠습니다.

리스트는 파이썬 오브젝트의 집합입니다. 다르게 설명하면 여러종류의 데이터를 한 곳에 저장하고 참조 할 수 있는 데이터 스트럭쳐입니다.

리스트란?

리스트는 중요한 data structure 중 하나입니다. 리스트는 오브젝트의 컬랙션(집합)입니다. 리스트는 시퀀스 타입입니다. 리스트는 iterator 오브젝트입니다. 리스트를 정의하는 방법을 알아보겠습니다. 리스트는 브라켓안에 컴마를 구분자로 사용하여 여러가지 데이터를 정의할 수 있습니다. 먼저 빈 리스트를 정의하여 보겠습니다. 빈 리스트를 정의하는 방법은 빈 브라켓으로 정의하는 방법과 list() 컨스트럭쳐를 사용하는 방법이 있습니다.

먼저 빈 브라켓으로 리스트를 정의해보겠습니다.

>>> []
[]

이번에는 리스트 컨스트럭쳐를 사용하여 보겠습니다.

>>> list()
[]

실제로 프로그램을 만들게 되면 빈 리스트를 정의해야 하는 경우가 많으니 잘 기억해두시기 바랍니다. 위의 두 방법 중 어느 방법을 사용하여도 괜찮습니다만, 많은 파이썬 프로그램머가 속도가 더 빠르다는 이유로 빈 브라켓으로 정의하는 방법을 선호하고 있습니다.

실제로 퍼포먼스를 비교해 보겠습니다.

# 이 코드는 ipython이나 notebook에서 실행해주세요.
In [1]: %timeit []
21.2 ns ± 0.419 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
 
In [2]: %timeit list()
52.9 ns ± 0.601 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

분명히 빈 브라켓을 사용하는 것이 더 빠른 것을 볼 수 있습니다. 하지만 몇 초도, 몇 밀리 세컨드고 아니고 몇십 나노세컨드의 차이이니 어느 쪽을 사용하여 괜찮다고 봅니다.

이번에는 1부터 5까지의 숫자를 이용하여 간단한 리스트를 정의한 뒤 출력해보겠습니다.

>>> numbers = [1, 2, 3, 4, 5]
>>> numbers
[1, 2, 3, 4, 5]

한 변수안에 1부터 5까지의 인트 데이터가 저장된 것을 볼 수 있습니다. 타입 함수를 사용하여 데이터의 타입을 확인해 보겠습니다.

>>> type(numbers)
<class 'list'>

데이터의 타입이 리스트라는 것을 확인했습니다. 이번에는 리스트의 기본 기능과 리스트 클래스가 제공하는 클래스 메소드를 사용해 보겠습니다.

파이썬이 기본적으로 제공하는 내장 함수인 len 함수를 사용하면 리스트의 아이템이 몇개인지, 즉 리스트의 길이를 확인할 수 있습니다. Len 함수를 사용하여 위에서 정의한 리스트의 길이를 확인해 보겠습니다.

>>> len(numbers)
5

리스트가 다섯개의 아이템을 가지고 있다는 것을 확인하였습니다.

파이썬은 리스트의 아이템을 순서대로 정렬할 수 있도록 sorted라는 내장 함수를 제공합니다.

>>> # 다섯개의 숫자를 순서없이 리스트안에 정의하겠습니다.
>>> numbers = [3, 2, 1, 5, 4]
>>> # 정의한 리스트를 소티드 함수를 사용하여 정렬해 보겠습니다.
>>> sorted(numbers)
[1, 2, 3, 4, 5]

여기서 꼭 기억해야 하는 포인트가 있는데요, sorted 함수를 사용하면 오리지널 리스트는 정렬되지 않고 정렬된 새로운 리스트가 리턴된다는 것을 기억하셔야 합니다.

오리지널 리스트를의 값이 변했는지 확인해보겠습니다.

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

보시다시피 오리지널 리스트는 변경되지 않았습니다. 정렬된 리스트를 리턴 값으로 받는게 목적이 아니고, 오리지널 리스트의 값을 변경하고 싶을 때는 sort라는 클래스 메소드를 사용하여야 합니다. 하지만 반대로 sort 메소드는 사용하면 오리지널 리스트는 정렬되지만 어떤 값도 리턴하지 않는다는 것을 기억하셔야 합니다.

sort 메소드를 사용하여 오리지널 리스트를 정렬해 보겠습니다.

>>> numbers.sort()
>>> numbers
[1, 2, 3, 4, 5]

오리지널 리스트가 정렬이 된 것을 확인하였습니다.

내장함수인 max와 min 함수를 사용하여 리스트 아이템의 최대값과 최소값을 확인 할 수도 있습니다.

max 함수를 사용하여 최대값을 출력해 보겠습니다.

>>> max(numbers)
5

이번에는 min 함수를 사용하여 최소값을 출력해보겠습니다.

>>> min(numbers)
1

sum 함수를 사용하여 모든 아이템의 합을 구할 수도 있습니다.

>>> sum(numbers)
15

이번에는 리스트의 기본 기능에 대해서 알아 보겠습니다. 리스트는 파이썬이 제공하는 6개의 시퀀스 타입 중 하나입니다. 파이썬의 시퀀스 타입 중에 또 다른 하나는 지난 강좌에서 공부한 스트링 타입입니다. 시퀀스의 뜻을 영어 사전에서 찾아보면 배열, 순서, 수순, 연속적인 사건들이라고 설명하고 있습니다. 즉 시퀀스 타입이란 데이터를 배열로서, 또는 순서대로 관리할 수 있는 타입을 말합니다. 시퀀스 타입은 순서가 있는 데이터이기 때문에 숫자로된 인덱스를 통하여 내부 아이템에 접근할 수 있습니다. 인덱스를 사용하여 스트링의 아이템에 엑세스가 가능한 것 처럼, 리스트 아이템 또한 인덱스를 사용하여 접근이 가능합니다. 또한 슬라이싱을 할 수도 있습니다. 파이썬은 제로 베이스 인덱스를 사용하므로 왼쪽 첫 번째의 아이템의 인덱스가 0이고 오른쪽을 이동할 수록 인덱스가 1씩 증가한다는 것을 지난 강좌에서 배웠습니다. 리버스 인덱스를 사용하여 마지막 아이템부터 접근할 수도 있습니다.

파이썬 씨퀀스 타입

str unicode list tuple buffer range 다시 1부터 5까지의 숫자를 리스트안에 정의해 보겠습니다.

>>> numbers = [1, 2, 3, 4, 5]

리스트의 첫 번째 아이템인 1을 출력해 보겠습니다.

>>> numbers[0]
1

마지막 아이템인 5를 출력해보겠습니다.

>>> numbers[4]
5

이번에는 리버스 인덱스를 사용하여 마지막 아이템인 5를 출력해 보겠습니다.

>>> numbers[-1]
5

슬라이싱을 사용하여 첫번째 3개의 아이템을 출력하여 보겠습니다.

>>> numbers[0:3]
[1, 2, 3]

스타트 인덱스가 0일 경우는 다음과 같이 생략을 하여도 됩니다.

>>> numbers[:3]
[1, 2, 3]

이번에는 마지막 세개의 아이템을 출력해보겠습니다.

>>> numbers[-3:]
[3, 4, 5]

이번에는 리스트의 기능 중에 가장 중요한 기능인 iterating에 대해서 확인해 보도록 하겠습니다.

파이썬 오브젝트 중에는 for loop 에서 사용이 가능한 iterator 오브젝트가 있습니다. 리스트도 iterator 오브젝트이며 for loop을 사용하여 각각의 아이템에 엑세스할 수 있습니다. 오브젝트가 iterator 오브젝트인지 아닌지는 iter 함수를 사용하여 확인 할 수 있습니다.

>>> iter(numbers)
<list_iterator object at 0x7fee58134a30>

리스트가 iterator 오브젝트라는 것을 확인하였습니다.

이번에는 스트링 오브젝트가 iterator 오브젝트인지 확인 해 보겠습니다.

>>> iter('string')
<str_iterator object at 0x7fee58134790>

이번에는 for loop을 사용하여 리스트안의 각각의 아이템을 출력해보겠습니다.

>>> for i in numbers:
...     print(i)
...
1
2
3
4
5

스트링 오브젝트도 iterator 오브젝트이기 때문에 for loop을 사용할 수 있습니다.

>>> for i in 'string':
...     print(i)
...
s
t
r
i
n
g

다음은 concatenating 기능입니다. 이 기능은 플러스 (+) 오퍼레이터를 사용하여 두 개의 리스트를 하나로 합치는 것을 말합니다.

>>> list_1 = [1, 2, 3]
>>> list_2 = [4, 5]
>>> new_list = list_1 + list_2
>>> new_list
[1, 2, 3, 4, 5]

에스터리스크 (asterisk) 오퍼레이터를 사용하여 리스트의 아이템을 복제할 수도 있습니다.

>>> new_list * 3
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]

각각의 아이템이 3개씩 복제된 것을 볼 수 있습니다.

리스트의 기본 기능

Indexing Slicing Iterating Concatenating Multiplying 리스트와 사용 가능한 빌트인 함수

len sorted max min sum 이번에는 클래스 메소드를 사용하여 보겠습니다.

먼저 리스트 클래스에는 어떤 메소드가 정의되어 있는지 help 함수를 사용하여 확인해보겠습니다.

>>> help(list)
Help on class list in module builtins:
 
class list(object)
|  list(iterable=(), /)
|
|  Built-in mutable sequence.
|
|  If no argument is given, the constructor creates a new empty list.
|  The argument must be an iterable if specified.
|
|  Methods defined here:
|
|  __add__(self, value, /)
|      Return self+value.
|
|  __contains__(self, key, /)
|      Return key in self.
|
|  __delitem__(self, key, /)
|      Delete self[key].
|
|  __eq__(self, value, /)
|      Return self==value.
|
:

먼저 리스트에 아이템을 추가하는 append 메소드를 사용해 보겠습니다.

>>> numbers = [1, 2, 3, 4, 5]
>>> numbers.append(6)
>>> numbers
[1, 2, 3, 4, 5, 6]

새로운 아이템 6이 마지막 아이템으로 추가 된것을 볼 수 있습니다.

이번에는 리스트와 리스트를 연결하는 extend 함수를 사용하여 보겠습니다.

>>> numbers.extend([7, 8])
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8]

기존의 리스트와 새로운 리스트가 하나의 리스트로 만들어졌습니다.

플러스 (+) 오퍼레이터를 사용하여 두 리스트를 결합할 수도 있습니다.

💡 오늘의 팁

두 리스트를 결합하기 위해서는 extend 또는 + 오퍼레이터를 사용하셔야 합니다. 절대 append 메소드를 사용하면 안됩니다!

여기서 주의할 점이 있는데요, 많은 초보자분들이 두개의 리스트를 결합하기 위해서 append 함수를 사용합니다. append 함수를 사용하면 어떤 결과가 나오는지 먼저 확인해 보겠습니다.

>>> numbers.append([9, 10])
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8, [9, 10]]

보시다시피 append 메소드를 사용하면 두개의 리스트가 결합되는 것이 아니고 두번째 리스트가 첫번째 리스트의 마지막 아이템으로 추가되니 주의하시기 바랍니다.

원하는 위치에 새로운 아이템을 추가하고자 할 때는 insert 메소드를 사용하시면 됩니다. insert 메소드에 전달되는 첫번째 인자는 새로운 아이템이 위치하게 될 인덱스이며, 두번째 인자는 아이템의 값입니다.

>>> numbers = [1, 2, 4, 5]
>>> numbers.insert(2, 3)
>>> numbers
[1, 2, 3, 4, 5]

이번에는 remove 메소드를 사용하여 아이템을 삭제하여 보겠습니다. remove 메소드를 사용할 때는 삭제하고자하는 아이템의 인덱스가 아닌 아이템의 값을 사용하여야 합니다.