for 루프에서 transaction.on_commit 콜백에 인자를 올바르게 넘기는 방법
·2020.10.26 12:00
for 루프에서 on_commit 콜백은 lambda 기본값으로 현재 값을 고정해야 한다.
transaction.atomic() 안에서 transaction.on_commit() 을 for 루프와 함께 쓸 때는, 콜백에 넘기는 변수의 평가 시점을 주의해야 한다.
예를 들어 추첨 이벤트에서 10명의 당첨자에게 커밋 후 알림을 보내려면 루프마다 콜백을 등록해야 한다. 하지만 lambda send_notification(user)처럼 작성하면, 루프가 끝난 뒤의 마지막 user 값만 참조되어 같은 사용자에게 알림이 반복 발송될 수 있다.
핵심 원인은 콜백이 실행될 때가 아니라 등록될 때의 현재 값을 고정하지 못한 데 있다. on_commit() 은 인자를 받지 않는 함수를 실행하므로, 런타임에 바깥 변수 user를 다시 읽게 되고, 그 시점에는 모든 콜백이 같은 마지막 값을 보게 된다.
해결 방법은 익명 함수의 매개변수 기본값으로 현재 값을 묶어두는 것이다.
- 잘못된 예:
transaction.on_commit(lambda send_notification(user)) - 잘못된 예:
transaction.on_commit(lambda user: send_notification(user)) - 올바른 예:
transaction.on_commit(lambda user=user: send_notification(user))
이렇게 하면 루프의 각 반복에서 user가 기본값으로 저장되므로, 커밋 후 콜백이 실행될 때도 각 당첨자에게 각각 알림이 전송된다.
이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.
요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.