코딩도장_Unit 11. 시퀀스 자료형 활용하기

김민주·2021년 12월 29일
0

AIFFEL_풀잎스쿨

목록 보기
3/23
post-thumbnail

리스트, 튜플, range, 문자열은 모두 값이 연속적(sequence)으로 이어져 있다는 공통점이 있다.

파이썬에서는 값이 연속적으로 이어진 자료형을 시퀀스 자료형(sequence types)라고 부른다.

11.1 시퀀스 자료형의 공통 기능 사용하기

시퀀스 자료형의 가장 큰 특징은 공통된 동작과 기능을 제공한다는 점이다.
시퀀스 자료형으로 만든 객체를 시퀀스 객체라고 하며, 시퀀스 객체에 들어있는 각 값을 요소(element)라고 부른다.

11.1.1 특정 값이 있는지 확인하기

시퀀스 객체 안에 특정 값이 있는지 확인하기 위해 in연산자를 사용하며, 값이 있으면 True, 없으면 False가 출력된다.

  • 값 in 시퀀스 객체
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> 30 in a
True
>>> 100 in a
False

반대로 innot을 붙이면 특정 값이 없는지 확인한다.

  • 값 not in 시퀀스 객체
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> 100 not in a
True
>>> 30 not in a
False
# not in은 특정 값이 없으면 True, 있으면 False가 출력된다.

튜플, range, 문자열도 같은 방법 활용 가능하다.

>>> 43 in (38, 76, 43, 62, 19)
True
>>> 1 in range(10)
True
>>> 'P' in 'Hello, Python'
True

11.1.2 시퀀스 객체 연결하기

시퀀스 객체는 + 연산자를 사용하여 객체를 서로 연결하여 새 객체를 만들 수 있다.

  • 시퀀스 객체1 + 시퀀스 객체2
>>> a = [0, 10, 20, 30]
>>> b = [9, 8, 7, 6]
>>> a + b
[0, 10, 20, 30, 9, 8, 7, 6]
# 변수를 만들지 않고 리스트 여러 개를 직접 연결해도 상관없다

단, 시퀀스 자료형 중에서 range+연산자로 객체를 연결할 수 없다.

>>> 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를 리스트 또는 튜플로 만들어서 연결한다.

>>> 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, ' + 'world!'
'Hello, world!'
# 파이썬 문자열 연결은 여러 가지 결과를 묶어서 한 번에 출력할 때 자주 사용

📎 참고) 문자열에 숫자 연결하기
+ 연산자로 문자열에 숫자를 연결하면 에러가 난다.

>> 'Hello, ' + 10
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    'Hello, ' + 10
TypeError: Can't convert 'int' object to str implicitly 

해결 : str을 사용하여 숫자(정수, 실수)를 문자열로 변환 (문자열에 +를 사용할 때는 어떤 형태의 값이든 str을 사용해서 문자열로 맞춰주면 된다.)

  • '문자열' + str(정수 또는 실수)
>> 'Hello, ' + str(10)      # str을 사용하여 정수를 문자열로 변환
'Hello, 10'
>> 'Hello, ' + str(1.5)     # str을 사용하여 실수를 문자열로 변환
'Hello, 1.5'

11.1.3 시퀀스 객체 반복하기

*연산자는 시퀀스 객체를 특정 횟수만큼 반복하여 새 시퀀스 객체를 만든다. (0 또는 음수를 곱하면 빈 객체가 나오면 실수는 곱할 수 없다.)

  • 시퀀스 객체 * 정수
  • 정수 * 시퀀스 객체
>>> [0, 10, 20, 30] * 3
[0, 10, 20, 30, 0, 10, 20, 30, 0, 10, 20, 30]
# 요소 0, 10, 20, 30이 들어있는 리스트를 3번 반복해서 새 리스트 생성

11.2 시퀀스 객체의 요소 개수 구하기

요소의 개수(길이)를 구할 때는 len함수를 사용한다.

  • len(시퀀스객체)

11.2.1 리스트와 튜플의 요소 개수 구하기

>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> len(a)
10  # 리스트 a에는 요소가 10개 들어있으므로 
>>> b = (38, 76, 43, 62, 19)
>>> len(b)
5  # 튜플 b에는 요소가 5개 들어있으므로 

11.2.2 range의 숫자 생성 개수 구하기

rangelen함수를 사용하면 숫자가 생성되는 개수를 수할 수 있다.

>>> len(range(0, 10, 2)) 
5
# range(0, 10, 2)는 0부터 9까지 2씩 증가

11.2.3 문자열의 길이 구하기

문자열도 시퀀스 자료형이므로 len함수를 사용한다.

>>> hello = 'Hello, world!'
>>> len(hello)
13  
# 콤마(,)와 공백까지 포함된 값 (문자열을 묶는 따옴표 는 제외)
# 문자열 안에 포함된 따옴표는 포함된다

📎 참고) UTF-8 문자열의 바이트 수 구하기

>> hello = '안녕하세요'
>> len(hello.encode('utf-8'))
15 
# 안녕하세요 5글자가 차지하는 실제 바이트수는 15바이트

UTF-8에서 한글 글자 하나는 3바이트로 표현

11.3 인덱스 사용하기

시퀀스 객체의 각 요소는 순서가 정해져 있으며, 이 순서를 인덱스라고 부른다. (인덱스(index) : 위치 값)
시퀀스 객체에 대괄호([])를 붙이고 대괄호([]) 안에 각 요소의 인덱스를 지정하면 해당 요소에 접근이 가능하다.

  • 시퀀스객체[인덱스]
>>> a = [38, 21, 53, 62, 19]
>>> a[0]    # 리스트의 첫 번째(인덱스 0) 요소 출력
38
>>> a[2]    # 리스트의 세 번째(인덱스 2) 요소 출력
53
>>> a[4]    # 리스트의 다섯 번째(인덱스 4) 요소 출력
19

주의할 점 : 시퀀스 객체의 인덱스는 항상 0부터 시작한다는 점이다. (대다수 프로그래밍 언어의 공통 사항)

튜플, range, 문자열도 []에 인덱스를 지정하면 해당 요소를 가져올 수 있다.

# 튜플
>>> 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'

📎 참고) 시퀀스 객체에 인덱스를 지정하지 않으면?
인덱스를 지정하지 않은 상태 -> 해당 객체 전체를 의미

>> a = [38, 21, 53, 62, 19]
>> a  # 인덱스를 지정하지 않으면 시퀀스 객체 전체를 뜻함
[38, 21, 53, 62, 19]

📎 참고) __getitem__ 메서드
시퀀스 객체에서 대괄호([])를 사용하면 실제로는 __getitem__메서드를 호출해 요소를 가져온다.

  • 시퀀스 객체.__getitem__(인덱스)
>> a = [38, 21, 53, 62, 19]
>> a.__getitem__(1)
21

11.3.1 음수 인덱스 지정하기

시퀀스 객체에 인덱스를 음수로 지정하면 뒤에서부터 요소에 접근한다.

>>> a = [38, 21, 53, 62, 19]
>>> a[-1]   # 리스트의 뒤에서 첫 번째(인덱스 -1) 요소 출력
19
>>> a[-5]   # 리스트의 뒤에서 다섯 번째(인덱스 -5) 요소 출력
38

튜플, range, 문자열도 음수 인덱스를 지정하면 뒤에서부터 요소에 접근한다.

# 튜플
>>> b = (38, 21, 53, 62, 19)
>>> b[-1]  # 튜플의 뒤에서 첫 번째(인덱스 -1) 요소 출력
19

# range
>>> r = range(0, 10, 2)
>>> r[-3]  # range의 뒤에서 세 번째(인덱스 -3) 요소 출력
4

# 문자열
>>> hello = 'Hello, world!'
>>> hello[-4]  # 문자열의 뒤에서 네 번째(인덱스 -4) 요소 출력
'r'

11.3.2 인덱스의 범위를 벗어나면?

시퀀스 객체를 만들면 요소의 개수는 정해져 있다. 이 범위를 벗어난 인덱스에 접근할 경우 IndexError가 발생한다.

>>> a = [38, 21, 53, 62, 19]
>>> a[5]    # 인덱스 5는 범위를 벗어났으므로 에러
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    a[5]
IndexError: list index out of range 
# 튜플, range, 문자열도 범위를 벗어난 인덱스를 지정하면 IndexError가 발생한다

11.3.3 마지막 요소에 접근하기

len함수로 리스트의 길이를 구한 뒤 이 길이를 인덱스로 지정한다.

>>> a = [38, 21, 53, 62, 19]
>>> len(a)  # 리스트의 길이를 구함
5
>>> a[5]  # 리스트의 길이를 인덱스로 지정
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    a[5]
IndexError: list index out of range 

인덱스는 0부터 시작하므로 길이가 5로 나왔다면 4(5-1)로 지정해야 마지막 요소가 나오게 된다.

>>> a[4]
19

[응용] 인덱스에 len을 조합

>>> a[len(a)]
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    a[len(a)]
IndexError: list index out of range

len(a)는 5로 인덱스가 범위를 벗어나 에러가 발생한다. 따라서 len(a)에서 1을 빼주어야 한다.

>>> a[len(a) - 1]    # 마지막 요소(인덱스 4) 출력
19

11.3.4 요소에 값 할당하기

시퀀스 객체는 []로 요소에 접근한 뒤 =로 값을 할당한다.

  • 시퀀스 객체[인덱스] = 값
>>> 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

여기서도 범위를 벗어난 인덱스는 지정할 수 없다.

>>> a[5] = 90
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    a[5] = 90
IndexError: list assignment index out of range 

튜플은 안에 저장된 요소를 변경할 수 없다. 따라서 튜플의 [] 인덱스를 지정한 뒤 값을 할당하면 에러가 발생한다. 마찬가지로 range와 문자열도 안에 저장된 요소를 변경할 수 없다.

# 튜플
>>> b = (0, 0, 0, 0, 0)
>>> b[0] = 38
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    b[0] = 38
TypeError: 'tuple' object does not support item assignment 

# range
>>> r = range(0, 10, 2)
>>> r[0] = 3
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    r[0] = 3
TypeError: 'range' object does not support item assignment 

# 문자열
>>> hello = 'Hello, world!'
>>> hello[0] = 'A'
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    hello[0] = 'A'
TypeError: 'str' object does not support item assignment 

즉, 시퀀스 자료형 중 튜플, range, 문자열은 읽기 전용이다.🔎

11.3.5 del로 요소 삭제하기

요소 삭제는 del뒤에 삭제할 요소를 지정해주면 된다.

  • del 시퀀스 객체[인덱스]
>>> a = [38, 21, 53, 62, 19]
>>> del a[2]
>>> a
[38, 21, 62, 19]  # 세 번째 요소인 53 삭제

리스트와 달리 튜플, range, 문자열은 저장된 요소를 삭제할 수 없다.

# 튜플
>>> b = (38, 21, 53, 62, 19)
>>> del b[2]
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    del b[2]
TypeError: 'tuple' object doesn't support item deletion 

# range
>>> r = range(0, 10, 2)
>>> del r[2]
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    del r[2]
TypeError: 'range' object doesn't support item deletion 

# 문자열
>>> hello = 'Hello, world!'
>>> del hello[2]
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    del hello[2]
TypeError: 'str' object doesn't support item deletion 

11.4 슬라이스 사용하기

슬라이스(slice)라는 말 그대로 시퀀스 슬라이스는 시퀀스 객체의 일부를 잘라내는 작업을 뜻한다.

  • 시퀀스 객체[시작인덱스:끝인덱스]
    시작 인덱스와 끝 인덱스를 지정하면 해당 범위의 리스트를 잘라서 가져올 수 있다. 단, 주의해야 할 점으로 끝 인덱스는 가져오려는 범위에 포함되지 않는다.(끝 인덱스는 가져오려는 인덱스에 +1해서 지정)
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[0:4]  # 인덱스 0부터 3까지 잘라서 새 리스트를 만듦
[0, 10, 20, 30]
>>> a[1:1]  # 인덱스 1부터 0까지 잘라서 새 리스트를 만듦
[]
>>> a[1:2]  # 인덱스 1부터 1까지 잘라서 새 리스트를 만듦
[10]

11.4.1 리스트의 중간 부분 가져오기

슬라이스 했을 때 실제 가져오는 요소는 시작 인덱스부터 끝 인덱스-1까지이다.

>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[4:7]  # 인덱스 4부터 6까지 요소 3개를 가져옴
[40, 50, 60]

슬라이스는 음수를 인덱스로 지정할 수도 있다.

>>> a[4:-1]  # 인덱스 4부터 -2까지 요소 5개를 가져옴
[40, 50, 60, 70, 80]

11.4.2 인덱스 증가폭 사용하기

슬라이스는 인덱스의 증가폭을 지정하여 범위 내에서 인덱스를 건너뛰며 요소를 가져올 수 있다.
주의할 점은 인덱스의 증가폭이지 요소의 값 증가폭이 아니라는 점이다.

  • 시퀀스 객체[시작인덱스:끝인덱스:인덱스증가폭]
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[2:8:3]  # 인덱스 2부터 3씩 증가시키면서 인덱스 7까지 가져옴
[20, 50]

인덱스 증가폭을 지정하더라도 가져오려는 인덱스(끝 인덱스-1)를 넘어설 수는 없다.

>>> a[2:9:3]  # 인덱스 2부터 3씩 증가시키면서 인덱스 8까지 가져옴
[20, 50, 80]

11.4.3 인덱스 생략하기

슬라이스를 사용할 때 시작 인덱스와 끝 인덱스를 생략할 수도 있다. 인덱스를 생략하는 방법은 시퀀스 객체의 길이를 몰라도 되기 때문에 자주 쓰이는 방식이다.

  • 시퀀스 객체[:끝인덱스]
  • 시퀀스 객체[시작인덱스:]
  • 시퀀스 객체[:]
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[:7]  # 리스트 처음부터 인덱스 6까지 가져옴
[0, 10, 20, 30, 40, 50, 60]

>>> a[7:]  # 인덱스 7부터 마지막 요소까지 가져옴
[70, 80, 90]

>>> a[:]  # 리스트 전체를 가져옴
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

11.4.4 인덱스를 생략하면서 증가폭 사용하기

  • 시퀀스 객체[:끝인덱스:증가폭]
  • 시퀀스 객체[시작인덱스: :증가폭]
  • 시퀀스 객체[: :증가폭]
>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[:7:2]  # 리스트의 처음부터 인덱스를 2씩 증가시키면서 인덱스 6까지 가져옴
[0, 20, 40, 60]

>>> a[7::2]  # 인덱스 7부터 2씩 증가시키면서 리스트의 마지막 요소까지 가져옴
[70, 90]

>>> a[::2]  # 리스트 전체에서 인덱스 0부터 2씩 증가시키면서 요소를 가져옴
[0, 20, 40, 60, 80]

시작 인덱스, 끝 인덱스, 인덱스 증가폭을 모두 생략하면 리스트 전체를 가져온다.

  • 시퀀스 객체[: :]
>>> a[::]  # 리스트 전체를 가져옴
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

즉, a[:]와 a[::]는 결과가 같다.

📎 참고) 슬라이스의 인덱스 증가폭을 음수로 지정하면?
인덱스 증가폭을 음수로 지정하면 요소를 뒤에서부터 가져올 수 있다.

>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>> a[5:1:-1]
[50, 40, 30, 20]

주의할 점은 인덱스가 감소하므로 끝 인덱스보다 시작 인덱스를 더 크게 지정해야 한다.
시작 인덱스와 끝 인덱스를 생략하면서 증가폭은 -1로 지정하게 될 경우 리스트 전체에서 인덱스를 1씩 감소기키면서 요소를 가져오기 때문에 리스트를 반대로 뒤집은 결과가 출력된다.

>> a[::-1]
[90, 80, 70, 60, 50, 40, 30, 20, 10, 0]

11.4.5 len 응용하기

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]

끝 인덱스는 가져오려는 요소의 인덱스보다 1 더 크게 지정해야 하므로 len(a)ㅇ에서 1을 빼지 않아야 한다.
즉, 길이가 10인 리스트는 [0:10]이라야 리스트 전체를 가져온다.

11.4.6 튜플, range, 문자열에 슬라이스 사용하기

파이썬에서는 튜플, range, 문자열도 시퀀스 자료형이므로 리스트와 같은 방식으로 슬라이스를 사용할 수 있다.

  • 튜플[시작인덱스:끝인덱스]
  • 튜플[시작인덱스:끝인덱스:인덱스증가폭]
>>> b = (0, 10, 20, 30, 40, 50, 60, 70, 80, 90)
>>> b[4:7]  # 인덱스 4부터 6까지 요소 3개를 가져옴
(40, 50, 60)
>>> b[4:]  # 인덱스 4부터 마지막 요소까지 가져옴
(40, 50, 60, 70, 80, 90)
>>> b[:7:2]  # 튜플의 처음부터 인덱스를 2씩 증가시키면서 인덱스 6까지 가져옴
(0, 20, 40, 60)

range에 슬라이스를 사용하면 지정된 범위의 숫자를 생성하는 range 객체를 새로 만든다.

  • range객체[시작인덱스:끝인덱스]
  • range객체[시작인덱스:끝인덱스:인덱스증가폭]
>>> r = range(10)
>>> r
range(0, 10)
>>> r[4:7]  # 인덱스 4부터 6까지 숫자 3개를 생성하는 range 객체를 만듦
range(4, 7)
>>> r[4:]  # 인덱스 4부터 9까지 숫자 6개를 생성하는 range 객체를 만듦
range(4, 10)
>>> r[:7:2]  # 인덱스 0부터 2씩 증가시키면서 인덱스 6까지 숫자 4개를 생성하는 range 객체를 만듦
range(0, 7, 2)

range는 요소가 모두 표시되지 않고 생성 범위만 표시된다. 요소를 보기위해서는 range객체를 list함수를 사용한다.

>>> list(r[:7:2])
[0, 2, 4, 6]

문자열도 슬라이스를 사용할 수 있다. 특히 문자열은 문자 하나가 요소이므로 문자 단위로 잘라서 새 물자열을 만든다.

  • 문자열[시작인덱스:끝인덱스]
  • 문자열[시작인덱스:끝인덱스:인덱스증가폭]
>>> hello = 'Hello, world!'
>>> hello[2:9]  # 인덱스 2부터 인덱스 8까지 잘라서 문자열을 만듦
'llo, wo'
>>> hello[2:]  # 인덱스 2부터 마지막 요소까지 잘라서 문자열을 만듦
'llo, world!'
>>> hello[:9:2]  # 문자열의 처음부터 인덱스를 2씩 증가시키면서 인덱스 8까지 잘라서 문자열을 만듦
'Hlo o'

모든 시퀀스 자료형은 같은 방식으로 슬라이스를 사용해 일부를 잘라낼 수 있다.

📎 참고) slice 객체 사용하기
파이썬에서는 slice객체를 사용하여 시퀀스 객체(시퀀스 자료형으로 만든 변수)를 잘라낼 수도 있다.

  • 슬라이스객체 = slice(끝인덱스)
  • 슬라이스객체 = slice(시작인덱스, 끝인덱스)
  • 슬라이스객체 = slice(시작인덱스, 끝인덱스, 인덱스증가폭)
  • 시퀀스객체[슬리아스객체]
  • 시퀀스객체.__getitem__(슬라이스객체)
>> range(10)[slice(4, 7, 2)]
range(4, 7, 2)
>> range(10).__getitem__(slice(4, 7, 2))
range(4, 7, 2)

물론 slice 객체를 하나만 만든 뒤 여러 시퀀스 객체에 사용하는 방법도 가능

>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>> s = slice(4, 7)  # 인덱스 4부터 6까지 자르는 slice 객체 생성
# 리스트
>> a[s]
[40, 50, 60]
# range
>> r = range(10)
>> r[s]
range(4, 7)
# 문자열
>> hello = 'Hello, world!'
>> hello[s]
'o, '

11.4.7 슬라이스에 요소 할당하기

시퀀스 객체는 슬라이스 범위를 지정하여 여러 요소에 값을 할당할 수 있다.

  • 시퀀스객체[시작인덱스:끝인덱스] = 시퀀스객체
>>> 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:5] = ['a', 'b', 'c', 'd', 'e']  # 인덱스 2부터 4까지 값 5개를 할당하여 요소의 개수가 늘어남
>>> a
[0, 10, 'a', 'b', 'c', 'd', 'e', 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]

주의할 점은 인덱스 증가폭을 지정했을 때는 슬라이스 범위의 요소 개수와 할당할 요소 개수가 정확히 일치해야 한다.

>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> a[2:8:2] = ['a', 'b']
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    a[2:8:2] = ['a', 'b']
ValueError: attempt to assign sequence of size 2 to extended slice of size 3 

# ValueError : 부적절한 값을 받았을 시 뜨는 에러

튜플, range, 문자열은 슬라이스 범위를 지정하더라도 요소를 할당할 수 없다.

# 튜플
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    b[2:5] = ('a', 'b', 'c')
TypeError: 'tuple' object does not support item assignment 

# range
>>> r = range(10)
>>> r[2:5] = range(0, 3)
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    r[2:5] = range(0, 3)
TypeError: 'range' object does not support item assignment 

# 문자열
>>> hello = 'Hello, world!'
>>> hello[7:13] = 'Python'
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    hello[7:13] = 'Python'
TypeError: 'str' object does not support item assignment 

11.4.8 del로 슬라이스 삭제하기

슬라이스 삭제는 del 뒤에 삭제할 범위를 지정해주면 된다.

  • 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로 요소를 삭제하면 원래 있던 리스트가 변경되며 새 리스트는 생성되지 않는다.

인덱스 증가폭을 지정하면 인덱스를 건너뛰면서 삭제된다.

>>> a = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> del a[2:8:2]  # 인덱스 2부터 2씩 증가시키면서 인덱스 6까지 삭제
>>> a
[0, 10, 30, 50, 70, 80, 90]

동일하게 튜플, range, 문자열은 del로 슬라이스를 삭제할 수 없다.

# 튜플
>>> b = (0, 10, 20, 30, 40, 50, 60, 70, 80, 90)
>>> del b[2:5]
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    del b[2:5]
TypeError: 'tuple' object does not support item deletion 

# range
>>> r = range(10)
>>> del r[2:5]
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    del r[2:5]
TypeError: 'range' object does not support item deletion 

# 문자열
>>> hello = 'Hello, world!'
>>> del hello[2:9]
Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    del hello[2:9]
TypeError: 'str' object does not support item deletion 

11.5 연습문제 : 최근 3년간 인구 출력하기

리스트 year에 연도, population에 서울시 인구수가 저장되어 있습니다. 다음 소스 코드를 완성하여 최근 3년간 연도와 인구수가 리스트로 출력되게 만드세요.

year = [2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018]
population = [10249679, 10195318, 10143645, 10103233, 10022181, 9930616, 9857426, 9838892]
 
print(year[-3:])
print(population[-3:])

# 실행결과
[2016, 2017, 2018]
[9930616, 9857426, 9838892]

최근 3년간의 연도와 인구수 출력 = 리스트의 마지막 요소 3개를 잘라서 출력

1) year[len(year) - 3:]
len 함수로 리스트의 길이를 구한 뒤 3을 빼서 시작 인덱스에 지정

2) year[-3:len(year)]
끝 인덱스에도 len 함수로 리스트의 길이를 구해서 넣음. (마지막 요소들을 출력할 때는 끝 인데스를 주로 생략)

11.6 연습문제 : 인덱스가 홀수인 요소 출력하기

다음 소스 코드를 완성하여 튜플 n에서 인덱스가 홀수인 요소들이 출력되게 만드세요.

n = -32, 75, 97, -10, 9, 32, 4, -15, 0, 76, 14, 2
 
print(n[1::2]
또는
n[1:12:2]
또는
n[1:len(n):2])

# 실행결과
(75, -10, 32, -15, 76, 2)

홀수는 1부터 시작, 2씩 증가하므로 시작 인덱스는 1, 인덱스 증가폭은 2.
튜플 전체에서 요소들을 구해야 하므로 끝 인덱스는 생략

profile
안녕하세요 :-) 잘 부탁드립니다!

0개의 댓글