Python이 함수에 인자를 전달하는 방식에 대한 이해는 데이터의 예기치 않은 변경을 방지하고 코드 설계를 올바르게 하는 데 매우 중요합니다.
전통적인 프로그래밍 언어인 C나 Java에서는 값에 의한 전달(copy by value) 또는 참조에 의한 전달(copy by reference)를 사용합니다. 그러나 Python은 다른 모델을 가지고 있습니다 — 객체 참조에 의한 호출(call by object reference) (때때로 "공유에 의한 호출(call by sharing)"이라고도 합니다).
많은 개발자들이 Python이 항상 참조로 또는 값으로 인자를 전달한다고 잘못 생각합니다. 이는 변경 가능한 객체가 호출하는 코드에서 예기치 않게 수정되는 상황으로 이어집니다.
Python에서 함수의 매개변수 값은 함수로 전달되는 객체에 대한 참조입니다. 이는 다음을 의미합니다:
예:
# 리스트 - 변경 가능(mutable) def add_item(lst): lst.append(42) my_list = [1, 2, 3] add_item(my_list) print(my_list) # [1, 2, 3, 42] # 정수 - 변경 불가능(immutable) def add_num(x): x = x + 1 num = 10 add_num(num) print(num) # 10
주요 특징들:
Python에서 항상 인자를 참조로 전달하나요?
아니요, Python은 객체에 대한 참조를 전달하며, 객체가 어떻게 동작하는지는 그것이 변경 가능한지 여부에 따라 다릅니다. 변경 불가능한 객체는 어떤 변경이 있더라도 새로운 객체를 생성합니다.
함수 내에서 변경 가능한 인자를 다시 할당하여 외부 객체에 영향을 미칠 수 있나요?
아니요. 함수 내에서 매개변수에 새 값을 할당하면, 외부 객체는 아무런 변화가 없습니다 — 여러분은 단지 로컬 참조를 변경하는 것입니다.
예:
def reassign_list(lst): lst = [99, 100] my_list = [1, 2, 3] reassign_list(my_list) print(my_list) # [1, 2, 3]
기본값으로 리스트를 받는 함수가 재호출 시 이상하게 작동하는 이유는 무엇인가요?
기본값은 함수 정의 시 한 번만 생성되며, 이를 변경하면(예: 요소 추가) 이후 모든 호출에 대해 변경됩니다.
def add_element(x, cache=[]): cache.append(x) return cache print(add_element(1)) # [1] print(add_element(2)) # [1, 2]
프로그래머는 함수를 호출하여 리스트를 전달하고 원래 리스트가 변경되지 않기를 기대하지만, 함수가 요소를 추가합니다.
장점:
단점:
프로그래머는 함수 내에서 리스트를 명시적으로 복사하여 원본을 변경하지 않고 무언가를 반환합니다:
def process_data(data): data = data.copy() # 또는 list(data) # 복사본으로 안전하게 작업 data.append('보고서') return data
장점:
단점: