파이썬 | 시퀀스(sequence) 자료형
1. 시퀀스 (sequence)
우리가 지금까지 배웠던 리스트, 튜플, 문자열, range
를 자세히 보면 공통점이 있다. 바로 이들 모두 연속적(sequence)으로 되어 있다는 것이다.
파이썬에서는 이와 같이 값들이 연속적으로 이어진 자료형을 시퀀스 자료형(sequence types) 이라고 한다.
이 시퀀스 자료형 중에는 주로 list, tuple, range, str 을 사용하고 그 외에도 bytes 와 bytearray 가 있다. 이에 대한 내용은 나중에 살펴보자.
시퀀스 자료형의 공통 기능
굳이 우리가 시퀀스 자료형을 따로 나눈 이유는 이들은 공통적인 동작과 기능을 수행할 수 있기 때문이다. 따라서 시퀀스 자료형의 기본적인 사용법을 알면 나중에 어떠한 시퀀스 자료형이 와도 큰 어려움 없이 사용할 수 있다.
특정 값이 있는지 확인 ( in
, not in
)
>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> 5 in a
True
>>> 10 in a
False
>>> 10 not in a
True
in
이라는 것을 사용하면 위와 같이 특정한 값이 시퀀스 자료형안에 있는지 확인할 수 있다. 그에 따른 리턴값은 불로 Ture
나 False
로 나온다.
또한 not in
을 사용하면 특정 값이 없는지 확인이 가능하다.
>>> 4 in (7,4,6,3)
True
>>> 7 in range(0,10,2)
False
>>> 'p' in 'python'
True
물론 리스트 외에 다른 시퀀스 자료형도 위와 같이 사용할 수 있다.
시퀀스 객체 연결하기
시퀀스 객체는 +
연산자를 사용하여 객체를 연결할 수 있다.
>>> a = 1,2,3
>>> b = [4,5,6]
>>> a + b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate tuple (not "list") to tuple
>>> a + a
(1, 2, 3, 1, 2, 3)
>>> b + b
[4, 5, 6, 4, 5, 6]
하지만 같은 자료형끼리만 더할 수 있다. 위의 예제에도 튜플 + 리스트를 하니까 오류가 나오는 것을 볼 수 있다.
또 예외가 하나 더 있는데
>>> range(0, 10) + range(10, 20)
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
range(0, 10) + range(10, 20)
TypeError: unsupported operand type(s) for +: 'range' and 'range'
range
+ range
는 할 수 없다. 이때는 range
를 튜플이나 리스트로 만들어서 더하면 된다.
>>> list(range(0, 10)) + list(range(10, 20))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> tuple(range(0, 10)) + tuple(range(10, 20))
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
문자열 + 숫자
문자열 + 숫자는 가능할까?
>>> 'hello' + 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
오류가 발생한다. 정수와 문자열을 연결하려고 하니까 오류가 발생하는 것이다. 만약 둘이 연결하고 싶다면 숫자를 문자열로 바꿔주면 된다.
>>> 'hello' + str(5)
'hello5'
이와 같이 str
로 형변환을 해준 다음에 더하면 된다.
시퀀스 객체 반복하기
앞서 [1, 2, 3] + [1, 2, 3]
의 결과는 [1, 2, 3, 1, 2, 3]
이였다. 그렇다면 곱하기를 하면 어떨까?
>>> a = [1,2,3]
>>> a * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
곱한 만큼 반복된 시퀀스가 나온다. (음수나 0을 곱하면 빈문자열이 나오고 실수를 곱할 수는 없다.)
앞서 range
는 +
연산을 사용할 수 없었다. 마찬가지로 *
또한 range
에서는 사용할 수 없다.
>>> range(0, 5, 2) * 3
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
range(0, 5, 2) * 3
TypeError: unsupported operand type(s) for *: 'range' and 'int'
따라서 이를 사용하기 위해서는 아까와 마찬가지로 리스트나 튜플로 바꿔주면 사용이 가능하다.
>>> list(range(0, 5, 2)) * 3
[0, 2, 4, 0, 2, 4, 0, 2, 4]
>>> tuple(range(0, 5, 2)) * 3
(0, 2, 4, 0, 2, 4, 0, 2, 4)
문자열은 *
를 사용할 수 있다.
>>> 'Hello, ' * 3
'Hello, Hello, Hello, '
요소 개수 구하기
>>> a = [10,20,30,40,50]
>>> len(a)
5
range 의 숫자 생성 개수 구하기
>>> len(range(0, 10, 2))
5
문자열 길이 구하기
>>> hello = 'Hello, world!'
>>> len(hello)
13
문자열 길이에는 띄어쓰기도 포함된 길이를 나타낸다.
UTF-8 문자열의 바이트 수 구하기
>>> hello = '안녕하세요'
>>> len(hello.encode('utf-8'))
15
문자열이 차지하는 실제 바이트 수를 구하려면 위와 같이 하면 된다. 한글은 한 글자의 3바이트 이기 때문에 15가 나온 것이다.
참고로 파이썬 3에서는 len
은 문자열의 길이를 리턴하지만 파이썬 2.7에서는 실제 바이트 수를 구해주는 차이점이 있다.
2. 인덱스
-리스트
>>> a = [38, 21, 53, 62, 19]
>>> a[0] # 리스트의 첫 번째(인덱스 0) 요소 출력
38
>>> a[2] # 리스트의 세 번째(인덱스 2) 요소 출력
53
>>> a[4] # 리스트의 다섯 번째(인덱스 4) 요소 출력
19
-튜플
>>> b = (38, 21, 53, 62, 19)
>>> b[0] # 튜플의 첫 번째(인덱스 0) 요소 출력
38
-range
>>> r = range(0, 10, 2)
>>> r[2] # range의 세 번째(인덱스 2) 요소 출력
4
-문자열
>>> hello = 'Hello, world!'
>>> hello[7] # 문자열의 여덟 번째(인덱스 7) 요소 출력
'w'
getitem
>>> a = [38, 21, 53, 62, 19]
>>> a.__getitem__(1)
21
__getitem__
메서드를 사용하여 요소를 직접 가져올 수도 있다.
음수 인덱스
>>> a = [38, 21, 53, 62, 19]
>>> a[-1] # 리스트의 뒤에서 첫 번째(인덱스 -1) 요소 출력
19
>>> a[-5] # 리스트의 뒤에서 다섯 번째(인덱스 -5) 요소 출력
38
인덱스로 음수를 지정하면 뒤에서 부터 요소에 접근하게 된다.
마지막 요소에 접근하기
인덱스에 음수 -1 을 사용하면 마지막 요소에 접근이 가능했었다. 그렇다면 다른 방법은 없을까?? len
을 사용하면 된다.
>>> a = [10,20,30,40,50]
다음과 같은 리스트에서 len(a)
는 5가 나올 것이다. 그런데 마지막 요소의 인덱스는 4이기 때문에 len(a) - 1
이다. 따라서 다음과 같이 하면 마지막 요소에 접근이 가능하다.
>>> a[len(a) - 1]
50
요소에 값 할당하기
>>> a = [0, 0, 0, 0, 0] # 0이 5개 들어있는 리스트
>>> a[0] = 38
>>> a[1] = 21
>>> a[2] = 53
>>> a[3] = 62
>>> a[4] = 19
>>> a
[38, 21, 53, 62, 19]
>>> a[0]
38
>>> a[4]
19
위와 같이 리스트에 값을 다시 할당할 수 있다.
그러나 튜플은 앞서 말했듯이 수정이 불가능하다. 따라서 위와 같이 튜플의 값을 바꾸려고 하면 오류가 발생한다.
요소 삭제하기 ( del )
>>> a = [38, 21, 53, 62, 19]
>>> del a[2]
>>> a
[38, 21, 62, 19]
3. 슬라이스
슬라이스는 말 그대로 무언가 일부를 잘라낸다는 뜻이다.
>>> a
[10, 20, 30, 40, 50]
>>> a[0:3]
[10, 20, 30]
[]
안에 시작 인덱스와 끝 인덱스를 지정하면 해당 범위의 요소들을 가져온다. 여기서 주의할 점은 끝 인덱스 요소는 포함되지 않는다는 것이다. 따라서 끝 인덱스를 실제로 가져오려면 인덱스보다 1을 더 크게 지정해줘야한다.
따라서 예를 들어 요소가 10개있는 리스트를 처음부터 끝까지 가져오기 위해서는 [0:9] 가 아니라 [0:10] 으로 슬라이스를 해야 전부 가져올 수 있다는 것이다.
>>> a
[10, 20, 30, 40, 50]
>>> a[1:1] # 인덱스 1부터 0까지 잘라서 새 리스트를 만듦
[]
>>> a[1:2] # 인덱스 1부터 1까지 잘라서 새 리스트를 만듦
[20]
따라서 [1:1] 는 아무것도 못 가져오고 [1:2] 는 인덱스 1 번의 요소만 가져오게 되는 것이다.
음수 인덱스 활용
>>> a = [10,20,30,40,50,60,70,80,90]
>>> a[6:-1]
[70, 80]
앞서 우리가 배운 음수 인덱스를 활용하면 위와 같이 끝에서 두번째 인덱스 까지의 요소를 가져올 수 있다. [6:-1] 이면 6번 인덱스부터 -1번 인덱스까지(포함x) 이기 때문에 실제로 가져오는 요소는 6번 인덱스부터 -2번 인덱스 까지 가져오는 것이다.
인덱스 증가폭
지금까지는 지정된 범위의 요소들을 가져왔다. 그러나 슬라이스는 증가폭을 지정하여 가져올수도 있다.
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[2:8:3] # 인덱스 2부터 3씩 증가시키면서 인덱스 7까지 가져옴
[20, 50]
인덱스 생략
인덱스를 생략해서 슬라이스를 활용하는 방법도 있다. 시퀀스 객체의 길이를 몰라도 되기 때문에 자주 쓰이는 방식이다. 주로 마지막 일부분만 출력할 때 자주 사용한다.
>>> a
[10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[:7]
[10, 20, 30, 40, 50, 60, 70]
>>> a[7:]
[80, 90]
또는 a[:]
와 같이 시작 인덱스와 끝 인덱스 둘다 생략하면 리스트 전체를 가져온다.
>>> a[:]
[10, 20, 30, 40, 50, 60, 70, 80, 90]
인덱스 생략이 가능하기 때문에 다음과 같은 예제도 가능하다.
>>> a[::2] # 리스트 전체에서 인덱스 0부터 2씩 증가시키면서 요소를 가져옴
[10, 30, 50, 70, 90]
슬라이즈 음수 증가폭
그렇다면 만약에 증가폭을 음수로 지정하면 어떻게 될까?
>>> a
[10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[5:1:-1]
[60, 50, 40, 30]
>>> a[5:1:-2]
[60, 40]
시작 인덱스부터 끝 인덱스까지 감소폭 만큼 감소하면서 가져오는데 끝 인덱스는 포함되지 않고 가져온다.
여기서 주의할 점은 인덱스가 감소하므로 끝 인덱스보다 시작 인덱스가 더 커야 한다는 점이다.
len 응용하기
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[0:len(a)] # 시작 인덱스에 0, 끝 인덱스에 len(a) 지정하여 리스트 전체를 가져옴
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[:len(a)] # 시작 인덱스 생략, 끝 인덱스에 len(a) 지정하여 리스트 전체를 가져옴
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
리스트 a 의 요소의 개수는 10개이다. 따라서 len(a)
는 10이고 즉 a[0:10]
과 같다. 여기서 끝 인덱스를 10으로 지정했는데 끝 인덱스는 포함하지 않고 0부터 9인덱스 까지 출력한다. 그런데 실제 마지막 요소의 인덱스는 9 이기 때문에 전부 출력되는 것이다.
slice 객체 사용
파이썬에서는 slice
객체를 사용하여 시퀀스 자료형을 잘라낼 수 있다.
- slice(끝인덱스)
- slice(시작인덱스, 끝인덱스)
- slice(시작인덱스, 끝인덱스, 인덱스증가폭)
>>> range(10)[4:7:2]
range(4, 7, 2)
>>> range(10)[slice(4, 7, 2)]
range(4, 7, 2)
>>> range(10).__getitem__(slice(4, 7, 2))
range(4, 7, 2)
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> s = slice(4, 7) # 인덱스 4부터 6까지 자르는 slice 객체 생성
>>> a[s]
[40, 50, 60]
>>> r = range(10)
>>> r[s]
range(4, 7)
>>> hello = 'Hello, world!'
>>> hello[s]
'o, '
슬라이스에 요소 할당
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[2:5] = ['a', 'b', 'c'] # 인덱스 2부터 4까지 값 할당
>>> a
[0, 10, 'a', 'b', 'c', 50, 60, 70, 80, 90]
슬라이스를 활용하면 위와 같이 원하는 구간에 요소를 바꿔줄 수 있다.
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[2:5] = ['a'] # 인덱스 2부터 4까지에 값 1개를 할당하여 요소의 개수가 줄어듦
>>> a
[0, 10, 'a', 50, 60, 70, 80, 90]
앞선 예제에서는 요소의 개수를 맞춰서 바꿔줬는데 위와 같이 요소의 개수를 맞춰주지 않아도 된다. 만약 할당된 요소의 개수가 적으면 그만큼 리스트의 요소의 개수도 줄어든다.
증가폭도 활용하여 아래와 같이 요소를 할당할 수 있다.
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[2:8:2] = ['a', 'b', 'c'] # 인덱스 2부터 2씩 증가시키면서 인덱스 7까지 값 할당
>>> a
[0, 10, 'a', 30, 'b', 50, 'c', 70, 80, 90]
del 로 슬라이스 삭제하기
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> del a[2:5] # 인덱스 2부터 4까지 요소를 삭제
>>> a
[0, 10, 50, 60, 70, 80, 90]
앞서 배운 del
을 사용하여 슬라이스를 삭제할 수 있다.
Author And Source
이 문제에 관하여(파이썬 | 시퀀스(sequence) 자료형), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jhon3242/파이썬-시퀀스sequence-자료형저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)