EXCELSIOR

BETTER WAY 6 - 한 슬라이스에 start, end, stride를 함께 쓰지 말자 본문

Python/Effective Python

BETTER WAY 6 - 한 슬라이스에 start, end, stride를 함께 쓰지 말자

Excelsior-JH 2018. 1. 29. 00:48

BETTER WAY 6 - 한 슬라이스에 start, end, stride를 함께 쓰지 말자

Item06 - Avoid Using start, end, and stride in a Single Slice


Python에는 기본 슬라이싱 Better Way 5 참고 뿐만 아니라 somelist[start:end:stride]처럼 슬라이스의 간격(stride)를 설정하는 문법도 있다. 
stride를 이용하면 시퀀스를 슬라이스 할 때 n번째 아이템을 가져올 수 있다.


1
2
3
4
5
6
7
8
9
10
11
# 예를 들어, 스트라이드를 이용하면 리스트에서 홀수와 짝수 인덱스를 쉽게 구분하여 가져올 수 있다.
= ['red''orange''yellow''green''blue''purple']
odds = a[::2]
evens = a[1::2]
print(odds)
print(evens)
 
'''출력결과
['red', 'yellow', 'blue']
['orange', 'green', 'purple']
'''
cs


문제는 stride를 사용할 경우 예상치 못한 동작을 해 버그가 생길 수도 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
# 바이트 문자열 또는 문자열을 역순으로 만드는 방법은 stride를 -1로 슬라이싱 하면된다.
= b'mongoose'
= x[::-1]
print('y =', y)
 
= '한글'
= w[::-1]
print('z =', z)
 
'''출력결과
y = b'esoognom'
z = 글한
'''
cs


위의 코드는 바이트 문자열이나 아스키(ASCII) 문자에는 잘 동작하지만, UTF-8 바이트 문자열로 인코딩된 유니코드 문자에는 에러가 발생한다.


1
2
3
4
= '한글'
= w.encode('utf-8')
= x[::-1]
= y.decode('utf-8')
cs

위의 코드에서는 stride에 -1을 입력했을 경우를 살펴보았다. 그렇다면 -1외의 값을 입력하면 어떨까?


1
2
3
4
5
6
7
8
= ['a''b''c''d''e''f''g''h']
print('a[::2]  =', a[::2]) # 처음부터 시작해서 매 두 번쨰 아이템 선택
print('a[::-2] =', a[::-2]) # 끝부터 시작해서 반대 방향으로 매 두 번째 아이템 선택
 
'''출력결과
a[::2]  = ['a', 'c', 'e', 'g']
a[::-2] = ['h', 'f', 'd', 'b']
'''
cs


1
2
3
4
5
6
7
8
9
10
11
12
# 2::2, -2::-2, -2:2:-2, 2:2:-2 의 차이를 살펴보자
print('a[2::2]   =', a[2::2])
print('a[-2::-2] =', a[-2::-2])
print('a[-2:2:-2]=', a[-2:2:-2]) # = a[-2:-6:-2]
print('a[2:2:-2] =', a[2:2:-2])
 
'''출력결과
a[2::2]   = ['c', 'e', 'g']
a[-2::-2] = ['g', 'e', 'c', 'a']
a[-2:2:-2]= ['g', 'e']
a[2:2:-2] = []
'''
cs



위의 코드는 start, end, stride가 같이 들어가 있으면 해석하기가 어렵다. 
이러한 문제를 방지하려면 stride를 start, end인덱스와 함께 사용하지 않는 것이 좋다.
stride를 사용할 경우 양수 값을 사용하고 start와 end 인덱스는 생략하는 것이 좋다. 
만약, stride를 start나 end 인덱스와 함께 사용해야 한다면 stride를 적용한 결과를 변수에 할당하고, 이 변수를 슬라이스한 결과를 다른 변수에 할당해서 사용하도록 한다.


1
2
3
4
5
6
7
= a[::2# ['a', 'c', 'e', 'g']
= b[1:-1]
print('c =', c)
 
'''출력결과
c = ['c', 'e']
'''
cs


정리

  • 한 슬라이스에 start, end, stride를 지정하면 혼란스러울 수 있다.
  • 슬라이스에 start와 end인덱스 없이 양수 stride값을 사용하다록 한다.
  • 한 슬라이스에 start, end, stride를 되도록이면 함께 사용하지 않도록 한다.


Comments