이펙티브 파이썬 - 5. 시퀀스를 슬라이스하는 방법을 알자
07 Sep 2018 | python effective
5. 시퀀스를 슬라이스하는 방법을 알자
- 파이썬은 시퀀스를 슬라이스해서 조각으로 만드는 문법을 제공
- 슬라이싱 대상 : list, str, bytes …
__getitem__
, __setitem__
매직메서드를 구현하는 클래스에서도 슬라이싱 적용 가능
- 기본 형태 :
somelist[start:end]
- start 인덱스는 포함, end 인덱스는 제외
a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print('First four:', a[:4])
print('Last four: ', a[4:])
print('Middle two:', a[3:-3])
$$$
Fisrt four: ['a', 'b', 'c', 'd']
Last four : ['e', 'f', 'g', 'h']
Middle two: ['d', 'e']
- 리스트 처음부터 슬라이스 할 때는 인덱스 0 생략
assert a[:5] == a[0:5]
- 리스트 끝까지 슬라이스 할 때도 마지막 인덱스 생략
assert a[5:] == a[5:len(a)]
- 리스트 끝을 기준으로 오프셋을 계산할 때는 음수로 계산 하는 것이 편함
- note: 리스트의 인덱스를 음수 변수로 지정하면 슬라이싱으로 뜻밖의 결과를 얻는 몇 가지 상황 중 하나가 발생하니 주의해야 함. (ex:
somelist[-n:]
이라는 구문은 n>1일때는 정상 작동하지만, n=0일때 somelist[-0:]
이되면 원본 리스트의 복사본을 만듬)
- 슬라이싱은
start
와 end
인덱스가 리스트의 경계를 벗어나도 적절하게 처리
- 하지만 리스트의 경계를 벗어난 인덱스를 직접 접근하면 예외가 발생
- 슬라이싱의 결과는 완전히 새로운 리스트
- 원본 리스트에 들어 있는 객체에 대한 참조는 유지
- 하지만 슬라이스한 결과를 수정해도 원본 리스트에 아무런 영향을 미치지 않음
b = a[4:]
print('Before: ', b)
b[1] = 99
print('After: ', b)
print('No Change: ', a)
$$$
Before: ['e', 'f', 'g', 'h']
After: ['e', 99, 'g', 'h']
No Change:['a', 'b,' 'c,' 'd', 'e', 'f', 'g', 'h']
- 할당에 사용하면 슬라이스는 원본 리스트에서 지정한 범위를 대체
a, b = c[:2]
같은 튜플 할당과 달리 슬라이스 할다으이 길이는 달라도 된다.
- 할당 받은 슬라이스의 앞뒤 값은 유지
- 리스트는 새로 들어온 값에 맞춰 늘어나거나 줄어듦
print('Before ', a)
a[2:7] = [99, 22, 14]
print('After ', a)
$$$
Before ['a', 'b,' 'c,' 'd', 'e', 'f', 'g', 'h']
After ['a', 'b', 99, 22, 14, 'h']
- 시작과 끝 인덱스를 모두 생략하고 슬라이스 하면 원본 리스트의 복사본을 얻는다
b = a[:]
assert b == a and b is not a
- 새 리스트를 할당하지 않고 슬라이스 시작과 끝 인덱스를 지정하지 않고 할당하면 슬라이스의 전체 내용을 참조 대상의 복사본으로 대체
b = a
print('Before', a)
a[:] = [101, 102, 103]
assert a is b # 여전히 같은 리스트 객체임
print('After', a) # 이제 다른 내용을 담음
$$$
Before ['a', 'b', 99, 22, 14, 'h']
After [101, 102, 103]
핵심정리
- 너무 장황하게 ㄴㄴ, start 인덱스에 0을 설정하거나 end 인덱스에
len(a)
이런거 ㄴㄴ
- 슬라이싱은 범위를 벗어난 start나 end를 허용하므로 편함
- list 슬라이스에 할당하면 원본 시퀀스에 지정한 범위를 참조 대상의 내용으로 대체 (길이가 달라도 동작)
5. 시퀀스를 슬라이스하는 방법을 알자
- 파이썬은 시퀀스를 슬라이스해서 조각으로 만드는 문법을 제공
- 슬라이싱 대상 : list, str, bytes …
__getitem__
,__setitem__
매직메서드를 구현하는 클래스에서도 슬라이싱 적용 가능
- 기본 형태 :
somelist[start:end]
- start 인덱스는 포함, end 인덱스는 제외
a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
print('First four:', a[:4])
print('Last four: ', a[4:])
print('Middle two:', a[3:-3])
$$$
Fisrt four: ['a', 'b', 'c', 'd']
Last four : ['e', 'f', 'g', 'h']
Middle two: ['d', 'e']
- 리스트 처음부터 슬라이스 할 때는 인덱스 0 생략
assert a[:5] == a[0:5]
- 리스트 끝까지 슬라이스 할 때도 마지막 인덱스 생략
assert a[5:] == a[5:len(a)]
- 리스트 끝을 기준으로 오프셋을 계산할 때는 음수로 계산 하는 것이 편함
- note: 리스트의 인덱스를 음수 변수로 지정하면 슬라이싱으로 뜻밖의 결과를 얻는 몇 가지 상황 중 하나가 발생하니 주의해야 함. (ex:
somelist[-n:]
이라는 구문은 n>1일때는 정상 작동하지만, n=0일때somelist[-0:]
이되면 원본 리스트의 복사본을 만듬)
- note: 리스트의 인덱스를 음수 변수로 지정하면 슬라이싱으로 뜻밖의 결과를 얻는 몇 가지 상황 중 하나가 발생하니 주의해야 함. (ex:
- 슬라이싱은
start
와end
인덱스가 리스트의 경계를 벗어나도 적절하게 처리- 하지만 리스트의 경계를 벗어난 인덱스를 직접 접근하면 예외가 발생
- 슬라이싱의 결과는 완전히 새로운 리스트
- 원본 리스트에 들어 있는 객체에 대한 참조는 유지
- 하지만 슬라이스한 결과를 수정해도 원본 리스트에 아무런 영향을 미치지 않음
b = a[4:]
print('Before: ', b)
b[1] = 99
print('After: ', b)
print('No Change: ', a)
$$$
Before: ['e', 'f', 'g', 'h']
After: ['e', 99, 'g', 'h']
No Change:['a', 'b,' 'c,' 'd', 'e', 'f', 'g', 'h']
- 할당에 사용하면 슬라이스는 원본 리스트에서 지정한 범위를 대체
a, b = c[:2]
같은 튜플 할당과 달리 슬라이스 할다으이 길이는 달라도 된다.- 할당 받은 슬라이스의 앞뒤 값은 유지
- 리스트는 새로 들어온 값에 맞춰 늘어나거나 줄어듦
print('Before ', a)
a[2:7] = [99, 22, 14]
print('After ', a)
$$$
Before ['a', 'b,' 'c,' 'd', 'e', 'f', 'g', 'h']
After ['a', 'b', 99, 22, 14, 'h']
- 시작과 끝 인덱스를 모두 생략하고 슬라이스 하면 원본 리스트의 복사본을 얻는다
b = a[:]
assert b == a and b is not a
- 새 리스트를 할당하지 않고 슬라이스 시작과 끝 인덱스를 지정하지 않고 할당하면 슬라이스의 전체 내용을 참조 대상의 복사본으로 대체
b = a
print('Before', a)
a[:] = [101, 102, 103]
assert a is b # 여전히 같은 리스트 객체임
print('After', a) # 이제 다른 내용을 담음
$$$
Before ['a', 'b', 99, 22, 14, 'h']
After [101, 102, 103]
핵심정리
- 너무 장황하게 ㄴㄴ, start 인덱스에 0을 설정하거나 end 인덱스에
len(a)
이런거 ㄴㄴ - 슬라이싱은 범위를 벗어난 start나 end를 허용하므로 편함
- list 슬라이스에 할당하면 원본 시퀀스에 지정한 범위를 참조 대상의 내용으로 대체 (길이가 달라도 동작)
Comments