정리 노트

Python의 list, tuple, dictionary, set 본문

개념 정리

Python의 list, tuple, dictionary, set

꿈만 꾸는 학부생 2022. 7. 2. 17:27
728x90

파이썬을 사용하다 보면 리스트, 딕셔너리, 튜플, set을 많이 다루게 된다. 이걸 1학년 때 배운 후로 잘 써먹고 있긴 한데 가끔 까먹을 때가 있다. 최근에 프로그래머스 사용하면서 이들의 존재를 잊을 때도 많다.(set이나 tuple 같은 거...) 그래서 한 번 시간을 내서 정리해보는 것도 나쁘지 않겠다 싶어 이 글을 쓴다. 네 가지를 한 글에 정리하려니 분량이 엄청나다!

이 글을 작성하는데 역시 파이썬 documentation을 참고했고, 1학년 때 썼던 교재와 그 때 당시의 교수님의 자료도 참고했다.

https://docs.python.org/ko/3.8/library/stdtypes.html#sequence-types-list-tuple-range

 

내장형 — Python 3.8.13 문서

다음 섹션에서는 인터프리터에 내장된 표준형에 관해 설명합니다. 기본 내장 유형은 숫자, 시퀀스, 매핑, 클래스, 인스턴스 및 예외입니다. 일부 컬렉션 클래스는 가변입니다. 제자리에서 멤버

docs.python.org

https://book.naver.com/bookdb/book_detail.naver?bid=9520328 

 

헬로! 파이썬 프로그래밍

이 책에서는 파이썬에 매료된 저자와 그의 아들이 함께 프로그래밍을 배워나가면서 간단한 프로그램부터 그래픽과 사운드가 가미된 게임까지 만드는 과정을 그렸다. 컴퓨터 프로그래밍을 처음

book.naver.com

리스트(list)

리스트는 파이썬에 내장된 sequence 형 데이타 타입이다. 리스트 안에는 여러 항목들을 담을 수 있다. C++이나 Java에서의 array와 다르게 파이썬의 리스트 안에는 다른 타입의 항목들을 하나의 리스트에 같이 담을 수 있다.

mylist = [5, 'Hello', 3.141592, 'A']

리스트의 인덱스는 0에서부터 시작한다. 1부터 시작하지 않는다! 그렇기에 mylist의 항목 'Hello'의 인덱스는 2가 아니라 1이다. 리스트에서 특정 위치의 항목을 가져오려면 아래와 같이 가져올 수 있다.

>>> mylist[0]
5

자르기

특정 항목 하나만 가져오는 것만이 아니라 일정 인덱스 범위의 내용들을 잘라서 복사해올 수도 있다. 인덱스의 시작과 끝부분 사이에 ':' 기호로 구분한다.

>>> my_list[0:2]
[5, 'Hello']

위에서 보는 것 처럼 인덱스 범위 설정에 주의해야한다. 인덱스 끝부분은 포함되는게 아니다. 끝부분의 바로 전까지만 잘라지는 것이다!

':' 앞의 숫자를 생략하면 처음부터를 의미하고 뒤의 숫자를 생략하면 끝까지를 의미한다. 둘 다 생략하면 처음부터 끝까지란 것이다.

>>> mylist = [5, 'Hello', 3.141592, 'A']
>>> mylist[:3]
[5, 'Hello', 3.141592]
>>> mylist[1:]
['Hello', 3.141592, 'A']
>>> mylist[:]
[5, 'Hello', 3.141592, 'A']

생성, 내용 추가, 삭제, 수정

리스트는 대괄호를 이용해 선언하고 각 항목마다 ','로 구분한다. 리스트는 비어있는 채로 선언할 수 있고, 항목들이 있는 형태로도 선언할 수 있다.

>>> empty_list = []
>>> no_empty_list = [0, 1, 2]

리스트에 내용을 추가할 때 세 가지 메서드를 사용할 수 있다.

메서드 설명
append 리스트의 끝에 항목을 추가
extend 리스트의 끝에 여러 항목들을 추가
insert 리스트의 특정 위치에 항목 하나를 추가

extend 메서드를 사용할 때 추가할 항목들을 리스트 형태로 작성한다. insert 메서드를 사용할 때 항목을 추가할 위치와 추가할 항목을 작성한다.

>>> empty_list.append('a')
>>> empty_list
['a']
>>> no_empty_list.extend([3, 4, 5])
>>> no_empty_list
[0, 1, 2, 3, 4, 5]
>>> empty_list.insert(0, 'z')
>>> empty_list
['z', 'a']

리스트의 내용을 삭제할 때도 세 가지 메서드를 사용할 수 있다.

메서드 설명
remove 리스트에서 하나의 항목을 삭제
del 리스트에서 항목(들)을 삭제
pop 리스트의 특정 위치의 항목을 반환, 삭제

remove를 사용할 때는 삭제할 항목을 직접 작성하고 pop을 사용할 때는 삭제할 항목이 있는 위치를 작성한다. 위치를 작성하지 않으면 기본적으로 마지막 위치의 항목을 반환, 삭제한다.

del도 pop처럼 삭제할 항목이 있는 위치를 작성할 수 있고, 삭제할 리스트의 이름을 직접 입력해 전체를 지울 수 있다.

remove할 때 없는 값을 지우려 한다면 ValueError, 비어있는 리스트에서 pop하려면 IndexError, del로 지운 리스트를 다시 호출하면 NameError가 발생한다.

>>> empty_list.remove('a')
>>> empty_list
['z']
>>> no_empty_list.remove(10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
>>> no_empty_list
[0, 1, 2, 3, 4, 5]

>>> item = no_empty_list.pop(2)
>>> item, no_empty_list
(2, [0, 1, 3, 4, 5])
>>> item = no_empty_list.pop()
>>> item, no_empty_list
(5, [0, 1, 3, 4])
>>> temp = []
>>> item = temp.pop()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: pop from empty list

>>> del no_empty_list[0]
>>> no_empty_list
[1, 3, 4]
>>> del no_empty_list[10]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> del no_empty_list[1:]
>>> no_empty_list
[0]
>>> del empty_list
>>> empty_list
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'empty_list' is not defined

리스트의 수정은 매우 간단하다. 리스트의 인덱스에 새 항목을 할당해주기만 하면 끝난다. 리스트의 길이를 넘어선 인덱스에 할당하려면 IndexError가 발생한다.

>>> no_empty_list[0] = 'B'
>>> no_empty_list
['B']
>>> no_empty_list[2] = 'D'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

인덱스 찾기, 순회, 정렬

어떤 항목이 리스트의 어느 인덱스에 있는지 알고 싶어질 때가 있다. 이럴 땐, index 메서드를 사용하면 알아낼 수 있다. 없는 항목에 대해 찾으려면 ValueError가 발생한다.

>>> test = ['z', 'c', 'x']
>>> test.index('c')
1
>>> test.index('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 'a' is not in list

리스트의 값들을 하나씩 순회하는데는 여러 가지 방법들이 있다. 내가 자주 쓰는 두 가지 방법은 아래와 같다.

>>> mylist = ['Hello', 'Monster']
>>> for word in mylist:
...     print(word)
...
'Hello'
'Monster'
>>> for i in range(len(mylist)):
...     print(mylist[i])
...
'Hello'
'Monster'

리스트를 정렬하는 방법도 2가지가 있다. sort 메서드를 사용하면 원본 리스트가 정렬되고, sorted라는 파이썬 내장 함수를 사용하면 원본 리스트 안의 항목들을 정렬한 사본 리스트를 반환한다.

역순으로 정렬하려면 메서드 인자로 reverse=True를 추가한다.

>>> alphabet = ['c', 'a', 'e', 'b']
>>> print(alphabet.sort())
None
>>> alphabet
['a', 'b', 'c', 'e']
>>> alphabet.sort(reverse=True)
>>> alphabet
['e', 'c', 'b', 'a']
>>> alphabet2 = ['z', 'y', 'f' , 'u']
>>> copied = sorted(alphabet2)
>>> alphabet2, copied
(['z', 'y', 'f' , 'u'], ['f', 'u', 'y', 'z'])
>>> copied2 = sorted(copied, reverse=True)
>>> copied, copied2
(['f', 'u', 'y', 'z'], ['z', 'y', 'u', 'f'])

다중 리스트

리스트의 항목으로 리스트를 가질 수 있다. 이러한 리스트에서 하나의 항목을 가져오려면 행과 열의 위치를 다 알려줘야한다. 하나만 알려줄 경우 인덱스 위치에 해당하는 행의 정보를 모두 가져온다.

>>> two_dim_list = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
>>> two_dim_list[0]
[0, 1, 2]
>>> two_dim_list[1][2]
5

튜플(tuple)

튜플은 불변적인 리스트이다. 즉, 튜플에는 삽입, 삭제, 수정, 정렬 기능이 없다. 튜플의 내용을 수정하려하면 TypeError가 발생한다. 한 번 튜플을 선언하면 끝이다. 그 외로는 리스트처럼 사용할 수 있다. 즉, 리스트처럼 여러 타입의 항목들을 담을 수 있고, 순회도 리스트처럼 가능하다.

튜플은 리스트와 달리 쉼표를 사용해 선언한다. 단일 항목만을 갖는 튜플이라도 무조건 끝에 쉼표를 붙여 튜플임을 표시한다.

>>> my_tuple = 'c', 1.11, 2
>>> my_tuple[2]
2
>>> tuple2 = 6,
>>> tuple2
(6,)
>>> my_tuple[2] = 7
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

딕셔너리(dictionary)

딕셔너리는 매핑형 객체로 해시 가능한 값(key)을 임의의 객체(value)에 대응한다. 딕셔너리의 각 항목은 key-value 쌍으로 이루어져있다. 여기서 사용되는 key는 거의 임의의 값을 사용한다.

"딕셔너리는 리스트와 다르게 순서가 정해져있지 않다!" 라고 알고 있었지만 파이썬 3.7 버전에서부터는 딕셔너리의 순서는 삽입한 순서임을 보장한다고 한다. 그러면 인덱스를 쓸 수 있지 않을까 생각이 들지만 아직 딕셔너리는 리스트처럼 인덱스를 통해 항목을 조회할 수 없다. 딕셔너리에서 항목을 조회하는 방법은 key값을 이용하는 것이다. 없는 key값을 이용해 조회하려 하면 KeyError를 일으킨다.

>>> test = {'a':1, 'b':2, 'c':3}
>>> test['b']
2
>>> 'a' in test
True
>>> test['d']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'd'

생성, 내용 추가, 삭제, 수정

나는 주로 딕셔너리를 새로 생성할 때 중괄호를 많이 이용한다. 중괄호 안에는 쉼표로 구분된 'key : value' 쌍을 나열해서 항목들을 작성한다.

딕셔너리의 또 다른 생성 방법은 dict 생성자를 이용하는 것이다.

>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> a == b == c == d == e
True

딕셔너리에 항목을 추가, 수정하는 방법은 리스트의 항목을 수정하는 방법과 동일하다.

딕셔너리에서 항목을 삭제하려면 del을 이용해 삭제할 수 있다. 없는 키를 가지고 삭제를 시도하면 KeyError를 일으킨다. 딕셔너리의 clear 메서드를 이용하면 딕셔너리 안의 모든 항목들을 지운다.

>>> a['four'] = 4
>>> a
{'one': 1, 'two': 2, 'three': 3, 'four': 4}
>>> a['one'] = 'ONE'
>>> a
{'one': ONE, 'two': 2, 'three': 3, 'four': 4}
>>> del a['five']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'five'
>>> del a['one']
>>> a
{'two': 2, 'three': 3, 'four': 4}
>>> a.clear()
>>> a
{}

그 외 유용한 메서드들

딕셔너리에서 여러 메서드들로 사용의 편리성을 제공한다. 자주 쓸만한 메서드들을 정리하면 아래와 같다.

메서드 설명
keys 딕셔너리 안의 모든 키를 리스트로 반환.
values 딕셔너리 안의 모든 값을 리스트로 반환.
items 딕셔너리 안의 모든 키-값 쌍을 튜플로 담은 리스트를 반환.
get 키가 사전에 있으면 값을 반환. 없으면 None을 반환.

위의 설명은 쉽게 쓴 설명이지 사실 정확히 얘기하면 keys, values, items 메서드는 리스트를 반환하는게 아니라 '딕셔너리 뷰 객체'를 반환한다. 딕셔너리 뷰에서 iteration을 통해 데이터를 뽑아낼 수 있고, 멤버쉽 검사를 지원한다는 점에서 리스트처럼 생각하면 편하겠다는 생각으로 리스트라 표현한 것이다. 리스트로 착각해 이를 인덱스로 접근하려 하면 TypeError가 발생한다.

>>> b = {'a': 'apple', 'b': 'banana', 'c': 'cheese', 'd': 'dragonfruit'}
>>> b.keys()
dict_keys(['a', 'b', 'c', 'd'])
>>> b.values()
dict_values(['apple', 'banana', 'cheese', 'dragonfruit'])
>>> b.items()
dict_items([('a', 'apple'), ('b', 'banana'), ('c', 'cheese'), ('d', 'dragonfruit')])
>>> for i in range(len(b.values())):
...     temp = b.values()[i]
...     print(temp)
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: 'dict_values' object is not subscriptable
>>> e = b.get('e')
>>> print(e)
None
>>> d = b.get('d')
>>> d
'dragonfruit'

메서드를 이용해 딕셔너리 내의 모든 항목들을 순회할 수 있다.

>>> for key, value in b.items():
...     key, value
...
('a', 'apple')
('b', 'banana')
('c', 'cheese')
('d', 'dragonfruit')

딕셔너리를 보기 좋게 정렬시킬 수는 있다. 다만, 몇 가지 과정을 거쳐야한다. 정렬하는 방법은 아래의 사이트에서 잘 설명하고 있다.

https://blockdmask.tistory.com/566

 

[python] 파이썬 딕셔너리 정렬

안녕하세요. BlockDMask입니다. 오늘은 파이썬 딕셔너리 정렬에 대해서 알아보겠습니다. 딕셔너리의 key를 기준으로 정렬도 해보고, value를 기준으로도 정렬을 해보겠습니다. 이번 딕셔너리 정렬에

blockdmask.tistory.com

세트(set)

set는 멤버십 검사, 중복 제거와 교집합, 합집합, 차집합, 대칭 차집합과 같은 수학 연산을 할 때 사용한다. set은 중괄호와 항목 간에 쉼표로 구분해서 생성할 수 있다. 비어있는 set를 만들려면 set 생성자를 통해 생성해야한다.

set는 순서가 정해져있지 않다. 그렇기 때문에 set에 대해 인덱싱을 하면 TypeError를 일으킨다.

>>> myset = {1, 2, 'a', 3}
>>> empty = set()
>>> myset
{1, 2, 'a', 3}
>>> empty
set()
>>> myset[2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'set' object is not subscriptable

내용 추가, 삭제

set에서는 내용을 수정할 수 없다. 리스트나 튜플처럼 인덱스를 가지고 있는 것도 아니고, 딕셔너리처럼 항목마다 키 값을 가지고 있는 것도 아니기 때문에 수정할 방법이 딱히 없다. 그렇기에 set에서는 원소들을 새로 추가하거나 삭제만 가능하다.

원소를 추가하는 방법에는 두 가지가 있다. 단일 원소를 추가하는 방법과 여러 원소들을 한 번에 추가하는 방법이다.

메서드 설명
add set에 하나의 원소를 넣는다.
update set에 리스트 안의 원소들을 넣는다.
>>> myset.add('b')
>>> myset
{1, 2, 'a', 3, 'b'}
>>> myset.update([3, 4, 5, 6, 7])
>>> myset
{1, 2, 'a', 3, 'b', 4, 5, 6, 7}

일부러 set안에 이미 있는 값을 또 추가해보니 알아서 단일 값으로만 남아있다. set는 수학에서의 집합처럼 생각하기 때문에 중복되는 원소를 허용하지 않는다.

 

원소를 지우는 방법에도 두 가지가 있다. 두 방식의 차이는 에러 발생의 여부에서 나타난다.

메서드 설명
discard 원소가 set에 있으면 삭제한다.
remove 원소가 set에 있으면 삭제한다. 없으면 KeyError를 발생시킨다.
>>> myset.discard('z')
>>> myset
{1, 2, 'a', 3, 'b', 4, 5, 6, 7}
>>> myset.remove('z')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'z'
>>> myset.remove('a')
>>> myset
{1, 2, 3, 'b', 4, 5, 6, 7}

집합 연산

위에서 잠깐 얘기했다싶이 set은 수학에서의 집합과 같다. 그렇기에 set끼리의 집합 연산도 가능하다. 합집합, 교집합, 차집합, 대칭차집합 연산이 가능하다.

>>> a = {1, 2, 4, 8, 16, 32}
>>> b = {2, 4, 6, 8, 10, 12}
>>> a & b
{8, 2, 4}
>>> a | b
{32, 1, 2, 4, 6, 8, 10, 12, 16}
>>> a - b
{32, 1, 16}
>>> b - a
{10, 12, 6}
>>> a ^ b
{32, 1, 16, 6, 10, 12}

 

728x90

'개념 정리' 카테고리의 다른 글

영상 처리의 세 가지 기본 연산  (2) 2022.09.21
Git(2)  (0) 2022.07.06
Git(1)  (0) 2022.07.05
wsgiref 모듈과 같이 WSGI 알아보기(Python)  (0) 2022.06.25
re 모듈과 같이 정규식 이해하기(Python)  (0) 2022.06.23