
파이썬의 슬라이싱(list[start:end:step])은 강력합니다. 리스트, 문자열, 튜플, bytes 등 시퀀스 타입이면 다 통하죠. 그런데 다른 언어에서 배열을 다루던 습관이 남아 있으면 필요 없는 0이나 len()을 끝까지 꾸역꾸역 쓰는 코드가 나옵니다. 틀린 건 아니지만, 파이썬다운 코드는 아니에요.
또 슬라이싱이 "원본의 일부를 참조하는 건지, 복사본을 만드는 건지" 헷갈려서 이상한 버그를 만드는 경우도 자주 봅니다. 리스트 슬라이싱은 새로운 리스트를 반환한다는 점, 이걸 꼭 기억해야 해요.
numbers = [10, 20, 30, 40, 50, 60, 70, 80]
# 처음부터 / 끝까지인데도 굳이 0과 len() 써주기
first_three = numbers[0:3] # ❌ 0은 생략 가능
last_two = numbers[len(numbers)-2:len(numbers)] # ❌ 장황함
# 음수 인덱스 활용 못 하고 복잡하게
last = numbers[len(numbers)-1] # ❌
# 슬라이스가 "뷰"인 줄 알고 원본 수정된다고 착각
copy = numbers[:]
copy.append(999)
print(numbers) # 원본은 그대로 (새 리스트이기 때문)
numbers[0:3]은 numbers[:3]과 완전히 같고, numbers[len(numbers)-2:]은 그냥 numbers[-2:]로 쓰면 됩니다. len()을 슬라이싱 안에서 쓰는 순간 코드에 냄새가 난다고 봐도 돼요.
numbers = [10, 20, 30, 40, 50, 60, 70, 80]
# 처음부터 → start 생략
first_three = numbers[:3] # [10, 20, 30]
# 끝까지 → end 생략
from_fourth = numbers[3:] # [40, 50, 60, 70, 80]
# 끝에서 몇 개 → 음수 인덱스
last_two = numbers[-2:] # [70, 80]
except_last = numbers[:-1] # 마지막 하나만 빼고
# 전체 복사 (얕은 복사)
copy = numbers[:] # 원본 그대로 새 리스트
# step 활용
every_other = numbers[::2] # [10, 30, 50, 70]
reversed_nums = numbers[::-1] # 뒤집기
슬라이싱은 범위를 벗어나도 에러 없이 조용히 처리한다는 특징도 있어요. numbers[:100]은 IndexError가 아니라 그냥 전체 리스트를 돌려줍니다. 반면 numbers[100]처럼 단일 인덱스로 접근하면 에러가 나요. 이 차이 때문에 방어적 코드를 덜 쓸 수 있습니다.
그리고 슬라이스 대입(slice assignment)도 알아두면 좋습니다. numbers[2:5] = [99]처럼 쓰면 리스트 일부를 다른 길이의 시퀀스로 바꿀 수 있어요. del numbers[2:5]로 일부만 삭제할 수도 있고요.
nums = [1, 2, 3, 4, 5]
nums[1:3] = [20, 30, 40] # 길이가 달라도 됨
print(nums) # [1, 20, 30, 40, 4, 5]
슬라이싱이 새 리스트를 만든다는 건 꼭 기억하세요. 원본을 수정하지 않는 안전한 연산이라는 뜻입니다. 단, 원소가 객체(딕셔너리·리스트 같은 가변 객체)라면 얕은 복사라서 내부 객체는 공유한다는 점만 주의하면 돼요.
0, len(x)는 생략하세요. x[:3], x[-2:]가 파이썬다운 방식입니다.-1, -2)를 적극 활용하세요.x[:]이 전체 복사 관용구예요.x[100])는 IndexError를 냅니다.x[a:b] = [...], del x[a:b] 같은 슬라이스 대입·삭제도 강력한 기능입니다.데이터 처리에서 거의 매일 씁니다. 대용량 CSV에서 헤더만 떼어내기(header, *rows = lines 언패킹과 조합), 로그 파일의 최근 N줄만 보기(lines[-100:]), 페이지네이션(items[offset:offset+page_size])이 전형적인 예시예요. 특히 문자열도 시퀀스라서 슬라이싱이 그대로 통합니다. URL에서 쿼리스트링 떼어내기(url[:url.index('?')]), 파일 확장자 제거(name[:-4]) 같은 상황에서 유용하죠.
성능이 중요한 상황에서는 한 가지 주의점이 있어요. 매우 큰 리스트에서 슬라이싱은 새 리스트를 만들기 때문에 메모리와 시간을 씁니다. 이런 경우에는 itertools.islice()나 제너레이터를 고려하는 게 낫습니다. 평범한 상황에서는 신경 쓸 필요 없지만, GB 단위 데이터에서는 체감이 달라집니다.