파이썬의 함수 인자 전달 방식 (Call by Object Reference)
함수 호출 시 인자 전달 방식
- Call by Value, Call by Reference 등 함수에의 인자 전달 방식은 각 프로그래밍 언어의 특성 또는 전달할 인자를 입력하는 코드에 따라 달라진다. 이를 잘 알아두지 않으면 의도한 바 대로 데이터가 변경되지 않거나, 의도하지 않았는데 변경되는 경우가 생기므로 유의해야 한다.
- 이번 포스팅에서는 함수 호출 시 인자 전달 방식의 종류에 대해 정리하고, 파이썬이 어떤 방식을 취하는지 알아보고자 한다.
- ‘~에 의한 호출(Call by ~)’과 더불어 ‘~에 의한 전달(Pass by ~)’이란 표현으로도 쓰인다.
함수와 Parameter와 Arguments
- 들어가기에 앞서 매개변수(parameter)와 인자(arguments)의 개념을 명확히 할 필요가 있다.
- 함수는 Input-Process-Output의 제조업 모델을 떠올리면 쉽다. 재료를 넣어 가공한 후 결과물을 생성하는 하나의 기계라고 생각하자.
- 함수를 정의하는 것은 기계를 만드는 것이다. 만들어도 작동시키기 전까지는 전혀 의미가 없다.
- 함수를 호출하는 것이 바로 기계를 작동시키는 것이다. 작동시키기 위해서는 때에 따라 재료가 필요하다.
- parameter는 함수 정의 시 함수 내부에서 작업될 대상이 할당되도록 만들어 둔 통로인 변수의 이름이다. 물론 딱히 들어갈 재료가 없다면 생략이 가능하다.
- arguments는 함수 호출 시 실제로 투입되는 입력값의 실체, 즉 재료 그 자체이다. 통로가 없다면 넣을 수 없고, 통로가 있어도 넣지 않으면 결과물이 생산되지 않는다.
Call by Value (값에 의한 호출)
- arguments를 함수에 넣을 때, 해당 arguments를 복사한 값을 parameter라는 변수에 할당한다. 그러므로 함수 밖의 arguments와는 무관하며, 함수 밖에서 arguments 실체가 변경되지 않는다.
- 함수 밖 arguments의 값과 함수 안 parameter에 할당된 값은 서로 다른 메모리 주소를 갖는다. 형태는 동일하나 서로 다른 실체인 셈이다.
Call by Address (주소에 의한 호출)
- arguments의 메모리 주소값이 parameter에 복사되어 할당된다. 함수 내에서 parameter에 할당된 값을 변경하면 arguments도 변경된다.
- parameter의 값은 arguments의 주소를 가리키는 또 다른 값이므로 서로 다른 메모리 주소를 갖는다. parameter는 arguments를 바라보는 pointer 역할을 한다.
- 결국 주소’값’을 할당하는 것이므로 값에 의한 호출이라고 해야한다는 논란이 있다.
Call by Reference (참조에 의한 호출)
- parameter에 arguments의 실체가 바로 할당되며, parameter의 값을 변경하면 arguments의 값도 변경된다.
- parameter와 arguments의 실제 메모리 주소가 같다. arguments라는 실체를 함수 내에서는 parameter라는 이름으로 부른다고 생각하면 된다.
- 위의 두 호출 방식이 C에서 사용되었다면, 이 방식은 C++에서 추가적으로 도입된 방식이라고 한다.
파이썬은 Call by Value일까 Call by Reference일까?
- 파이썬은 위에 기술된 모든 방식과 또다른 양상을 보인다. 이를 이해하기 위해서는 파이썬에서 모든 것은 객체라는 점에 주목해야 한다.
- 파이썬은 변수에 값을 할당할 때, 객체를 만들고 그 객체를 변수가 가리키게 한다.
- 값을 나타내는 객체는
type
과 reference counter
라는 영역을 갖는다.
type
은 해당 값의 자료형을 나타낸다.
reference counter
는 몇 개의 식별자가 해당 값을 참조하고 있는지를 나타내는데, 이게 0일 경우 garbage collector에 의한 메모리 해제(delocate) 대상이 된다.
- 파이썬은 함수 밖에서 arguments가 변경되는 경우도, 변경되지 않는 경우도 있다. 이는 arguments의 type에 따라 결정된다.
- arguments의 type이
list
, dict
, set
등의 객체, 즉 Mutable Object일 때는 Call by Reference의 방식으로 동작하여 arguments의 실제 값이 직접 변경된다.
- arguments의 type이
str
, int
, tuple
등의 객체, 즉 Immutable Object일 때는 Call by Value의 방식으로 동작하여 arguments의 실제 값이 아닌 parameter에 할당되기 위해 복사된 값에 대해 process 작업을 수행한다.
- 이렇듯 파이썬은 값의 type이 어떻게 지정되어있느냐에 따라 달리 동작하므로 Call by Assignment라고 불리기도 한다.
- Call by Object나 Call by Sharing이라고 불리는 경우도 있다.
개인적으론 정확하게 특징을 반영하는 wording 같지는 않다만
결론
- 파이썬의 함수 인자 전달 방식은 Call by Object Reference (객체 참조에 의한 호출)이다.
느낀 점
- 파이썬 배울 때 이 개념을 듣고 굉장히 생소했는데, 객체와 메모리 등에 대해 조금이나마 더 잘 알고 나니 이해가 되어 기쁘다.
참고자료
hanana1253문정동에서 코딩하는 하나나입니다.