리스트
변수는 하나의 값을 담습니다. 리스트는 여러 값을 순서대로, 하나의 이름 아래 담습니다. 리더보드는 순위가 매겨진 점수들의 나열입니다. 퀴즈는 질문들의 모음입니다. 관련된 값들의 그룹을 다루어야 할 때, 리스트가 필요합니다.
리스트 생성하기
대괄호 안에 값들을 쉼표로 구분합니다. 리스트는 어떤 타입의 조합도 담을 수 있으며, 빈 리스트는 유효하고 시간이 지나면서 채워 나갈 시작점으로 흔히 사용됩니다.
scores = [87, 92, 74, 65, 91]
players = ["민준", "서연", "지호"]
mixed = ["민준", 87, True, 3.14] # 모든 타입 가능, 다만 드묾
empty = []인덱싱과 슬라이싱
리스트는 문자열과 같은 번호 체계를 사용합니다: 위치는 0부터 시작하고, 음수는 끝에서부터 셉니다. 위치로 어떤 항목이든 읽을 수 있습니다. 리스트는 가변적이므로 특정 위치에 쓸 수도 있습니다.
scores = [87, 92, 74, 65, 91]
scores[0] # 87 (첫 번째)
scores[-1] # 91 (마지막)
scores[1:3] # [92, 74]
scores[:2] # [87, 92]
scores[::-1] # [91, 65, 74, 92, 87] (역순)
scores[0] = 90 # 가변: 동작함 (문자열은 TypeError 발생)항목 추가하기
항목을 추가하는 세 가지 방법이 있습니다. append()는 끝에 단일 항목을 추가하며 거의 항상 사용하게 될 메서드입니다. insert()는 특정 위치에 추가합니다. extend()는 다른 리스트를 병합합니다.
scores = [87, 92, 74]
scores.append(65) # [87, 92, 74, 65]
scores.insert(1, 100) # [87, 100, 92, 74, 65]
scores.extend([55, 71]) # [87, 100, 92, 74, 65, 55, 71]흔한 실수: 리스트를 append()에 넣으면 전체 리스트를 하나의 항목으로 추가해서 리스트 안에 리스트가 생깁니다. 병합하려면 extend()를 사용하세요:
scores.append([55, 71]) # [..., [55, 71]] 중첩 리스트, 의도와 다를 가능성 큼
scores.extend([55, 71]) # [..., 55, 71] 병합됨, 올바름항목 제거하기
항목을 제거하는 네 가지 도구가 있습니다. remove()는 값으로 검색합니다. pop()은 위치로 제거하고 그 항목을 반환합니다. del은 위치로 제거하되 반환값이 없습니다. clear()는 리스트 전체를 비웁니다.
scores = [87, 92, 74, 65, 91]
scores.remove(74) # 74의 첫 번째 발생을 제거
scores.pop() # 마지막 항목 제거 후 반환 (91)
scores.pop(0) # 위치 0의 항목 제거 후 반환 (87)
del scores[1] # 위치 1에서 제거, 반환값 없음
scores.clear() # 전부 제거remove()는 값이 리스트에 없으면 ValueError를 발생시킵니다. 확신할 수 없다면 먼저 in으로 확인하세요:
if 74 in scores:
scores.remove(74)정렬
sorted()는 새로 정렬된 리스트를 반환하고 원본은 그대로 둡니다. .sort()는 리스트를 그 자리에서 정렬하고 None을 반환합니다. 이 차이는 들리는 것보다 훨씬 중요합니다.
scores = [87, 42, 96, 55, 71]
ranked = sorted(scores) # [42, 55, 71, 87, 96] (새 리스트)
scores.sort() # 그 자리에서 정렬, None 반환
scores.sort(reverse=True) # [96, 87, 71, 55, 42]
result = scores.sort() # result는 정렬된 리스트가 아닌 None유용한 연산
파이썬에는 리스트에서 직접 동작하는 내장 도구들이 있습니다. len(), sum(), min(), max()는 끊임없이 사용하게 될 네 가지입니다.
scores = [87, 92, 74, 65, 91]
len(scores) # 5
sum(scores) # 409
min(scores) # 65
max(scores) # 92
scores.count(87) # 1
scores.index(74) # 2
74 in scores # True
74 not in scores # False
scores.copy() # 얕은 복사
scores.reverse() # 그 자리에서 역순으로반복
for 루프는 리스트를 한 번에 한 항목씩 순회합니다. for 뒤의 변수가 각 항목을 차례대로 받습니다. 위치도 함께 필요할 때는 enumerate()가 수동 카운터 없이 둘 다 제공합니다.
players = ["민준", "서연", "지호"]
for player in players:
print(player)
for i, player in enumerate(players, start=1):
print(f"{i}. {player}")
# 1. 민준
# 2. 서연
# 3. 지호for 루프와 enumerate
for와 enumerate()는 제어 흐름 장에서 완전히 다룹니다. 짧게 말해: for player in players는 각 항목당 한 번 실행되며, enumerate()는 매 반복마다 위치와 값을 모두 제공합니다.
중첩 리스트
리스트는 다른 리스트를 포함할 수 있습니다. 이는 그리드나 테이블을 표현하는 방법입니다: 행들의 리스트이며, 각 행은 값들의 리스트입니다. 두 쌍의 대괄호로 항목에 접근합니다: 첫 번째는 행을 선택하고, 두 번째는 열을 선택합니다.
grid = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
grid[0] # [1, 2, 3]
grid[1][2] # 6 (행 1, 열 2)가변성: 함정
이는 거의 모든 사람을 놀라게 합니다. 리스트를 새 변수에 할당해도 복사본이 만들어지지 않습니다. 두 이름 모두 같은 리스트를 가리킵니다. 하나를 변경하면 다른 것도 변경됩니다. 독립적인 복사본을 얻으려면 명시적으로 요청해야 합니다.
a = [1, 2, 3]
b = a # b는 복사본이 아니다; 같은 리스트를 가리킨다
b.append(4)
print(a) # [1, 2, 3, 4] (변경됨: a와 b는 같은 리스트)b = a.copy() # 독립적인 복사본
b = list(a) # 같은 결과
b = a[:] # 역시 동일
# 중첩 리스트는 여전히 내부 객체를 공유한다:
matrix = [[1, 2], [3, 4]]
copy = matrix.copy()
copy[0].append(99)
print(matrix) # [[1, 2, 99], [3, 4]] (내부 리스트가 공유됨)추가 메서드
| 메서드 | 하는 일 |
|---|---|
.append(item) | 끝에 추가 |
.insert(i, item) | 위치 i에 삽입 |
.extend(iterable) | 이터러블의 모든 항목 추가 |
.remove(value) | 값의 첫 번째 발생 제거 |
.pop(i) | 위치 i의 항목 제거 후 반환 (기본값: 마지막) |
.clear() | 모든 항목 제거 |
.index(value) | 첫 번째 발생의 위치 |
.count(value) | 발생 횟수 |
.sort() | 그 자리에서 정렬 |
.reverse() | 그 자리에서 역순으로 |
.copy() | 얕은 복사본 반환 |
실전에서
점수 추적기 구축하기: 결과를 추가하고, 정렬하고, 요약을 출력합니다.
scores = []
scores.append(87)
scores.append(54)
scores.append(92)
scores.append(67)
scores.append(45)
scores.sort(reverse=True)
print(f"순위별 점수: {scores}")
print(f"최고점: {scores[0]}")
print(f"최저점: {scores[-1]}")
print(f"평균: {sum(scores) / len(scores):.1f}")
print(f"상위 3개: {scores[:3]}")
