최근 파이썬에서 dict에 대한 iteration 동작에 대해 이해하게 된 부분을 정리하고자 한다.
student_score = {
"희진": 97,
"영희": 60,
"다정": 77,
"병수": 79,
"창현": 89,
}
위 dict 정보에서, 가장 높은 점수를 가진 학생의 이름을 구하는 문제를 풀어본다.
여러 방법이 있는데, 아래처럼 max 함수와 key 지정을 사용하면 짧은 코드로 해결 가능하다.
max_name = max(student_score, key=student_score.get)
max_score = student_score[max_name]
print(f'점수가 가장 높은 학생은 {max_name}, 그 점수는 {max_score}점이다.')
점수가 가장 높은 학생은 희진, 그 점수는 97점이다.
위 코드에서 max 함수부분이 어떻게 동작하는 건지 자세하게 연구를 해봤다.
핵심 포인트: 파이썬의 dict에 대한 직접 iteration이 수행될 때는, Key만 순회한다. Value를 순회하지는 않는다.
student_score = {
"희진": 97,
"영희": 60,
"다정": 77,
"병수": 79,
"창현": 89,
}
for key in student_score:
print(key)
희진
영희
다정
병수
창현
위를 통해 dict에 대한 직접 iteration은, key 값만을 순회하는 것을 알 수 있다.
같은 이유로, 만약 max(student_score)를 호출하면 student_core의 key들만을 기준으로 최솟값을 찾는다. (즉 value에 대한 값 확인은 전혀 발생하지 않는다)
student_score = {
"희진": 97,
"영희": 60,
"다정": 77,
"병수": 79,
"창현": 89,
}
print(max(student_score))
다정
사전(알파벳 순으로) 최댓값을 찾기 때문에, "다정"이 출력된다.
max() 함수에 'key' 파라미터에 특정 함수를 지정하게 되면, dict의 key들 자체가 아닌, 각 key를 해당 함수에 아규먼트로 넘긴 결과값을 기준으로 정렬했을때에 최대 결과값을 가진 key가 max()의 리턴값으로 반환된다.
student_score = {
"희진": 97,
"영희": 60,
"다정": 77,
"병수": 79,
"창현": 89,
}
max_name = max(student_score, key=student_score.get)
max_score = student_score[max_name]
print(f"점수가 가장 높은 학생은 {max_name}, 그 점수는 {max_score}점이다.")
여러 key들 중에서, student_score.get()에 각 key값을 아규먼트로 넘긴 결과값 중 최댓값은 97이므로, "희진"이 max()의 결과값이 된다.
-> max()는 각 key들에 대해 iteration을 돌면서, key를 하나씩 차례로 student_score.get()에 전달한다. student_score.get ()은 dict의 value 값을 반환한다. 그러면 max()는 이 반환된 값들을 기준으로 최소값을 찾고, 최소값에 매칭되는 key를 찾아서 리턴한다.
참고로, max의 key 파라미터에는 lambda 함수도 입력이 가능하다.
아래 예시처럼, lambda 함수는 key를 아규먼트로 받아서 value를 리턴하는 함수이므로 잘 동작한다.
max_name = max(student_score, key=lambda x: student_score.get(x))
max_score = student_score[max_name]
print(f"점수가 가장 높은 학생은 {max_name}, 그 점수는 {max_score}점이다.")
점수가 가장 높은 학생은 희진, 그 점수는 97점이다
이처럼 파이썬 dict에 대한 직접 iteration은 key에 대해서만 순회한다는 것을 확인했다.
그렇다면.. 대신 value에 대해서 순회하려면?
for value in student_score.values():
print(value)
97
60
77
79
89
위처럼 for문에서는 임의로 values()를 지정해줘야 한다.
max() 함수에서 value들만을 대상으로 iterate하게 할 수 있는 방법은 없었다.
또는.. key와 value 모두에 대해 순회하려면?
for key, value in student_score.items():
print(key, value)
희진 97
영희 60
다정 77
병수 79
창현 89
for 문에서 임의로 items()를 지정해줘야 한다. 각 iteration마다 (key, value)라는 tuple 형태로 출력된다.
위 items()를 활용해서도 본 문제의 해결이 가능하다. 각 (key, value) 쌍에 대해 iterate를 할 수 있기 때문이다.
lambda 함수를 활용하면 max에 넘길 별도의 key 파라미터 함수는 작성하지 않아도 된다.
student_score = {
"희진": 97,
"영희": 60,
"다정": 77,
"병수": 79,
"창현": 89,
}
max_name, max_score = max(student_score.items(), key=lambda x: x[1])
print(f"점수가 가장 높은 학생은 {max_name}이며, 그 점수는 {max_score}점입니다.")
max() 함수는 이제 student_score라는 dict가 아닌 student_score.items() 라는 dict_items 라는 시퀀스를 iterate하게 된다.
이제 매 iteration 마다 (key, value) tuple을 순회하며, lambda 함수에는 아규먼트로 (key, value)가 전달된다.
lambda 함수는 tuple을 받으면 그중에 두번째 값, 즉 value를 리턴한다.
따라서, max() 함수는 value를 기준으로 최댓값을 가지는 (key, value) 값을 리턴하게 된다.
결론
파이썬에서 dict에 대한 직접 iteration은 key에 대해서만 수행된다.
그리고 이 성질을 이용해서, max() 함수와 같은 곳에서 key iteration이 수행된다. max의 key 파라미터 함수는 각 iteration의 key를 아규먼트로 받아서 최댓값의 기준으로 삼을 특정 리턴값을 만들어낸다.
위 글에서는 max() 함수에 대해서만 다뤘는데, min() 함수에서도 key iteration 원리는 동일하게 적용된다.
'Python > 문법' 카테고리의 다른 글
[Python] Static Method (@staticmethod) (0) | 2024.12.05 |
---|---|
[Python] Class 변수와 Instance 변수 사용시 조심할 점 (0) | 2024.12.05 |
[Python] Iteration의 원리(Iterator Protocol) (1) | 2024.12.04 |
[Python] Local 변수 vs Global 변수, global 키워드 사용법 (3) | 2024.12.02 |
[Python] Immutable(불변) vs. Mutable(가변) (1) | 2024.11.28 |