반응형

최근 파이썬에서 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 원리는 동일하게 적용된다.

반응형

+ Recent posts