이전 포스팅에서 지역변수, 전역변수를 다루면서 지역 변수는 함수 안에서만 효력을 가진다고 얘기 했습니다.
그런데 함수를 인자로 전달시 전달된 인자가 영향을 받는 부분이 있습니다.
예제를 통해 알아봅니다.
아래 함수는 숫자와 리스트를 전달하여 각 자료형에 변화를 주는 내용입니다.
아래 예제를 보면 숫자로 선언된 x는 함수를 호출하고도 영향을 받지 않고 함수 호출 전인 10의 값을 출력하였습니다.
그런데 리스트 자료형은 함수 호출전은 [1, 2, 3] 이라고 선언을 했는데 함수 호출 후 함수에서 추가한 10의 값이 추가되어서 [1, 2, 3, 10 ] 이라고 출력됩니다.
파이썬에서불가변객체( immutable), 가변객체( mutable )가 있습니다. 숫자형은 불가변객체에 속하고 리스트는 가변객체에 속합니다.
자료형 복사에서 copy와 deepcopy가 있었던 것을 기억하시나요?
이때는 가변/ 불가변에 대한 언급을 하지 않았었습니다. 다소 내용이 어려워질 수 있어서 언급을 하지 않았습니다.
이것 역시 가변/불가변의 영향을 받아서 copy와 deepcopy가 있는 것 입니다.
- 가변( mutable) 객체 : 객체의 값을 수정 가능합니다. 리스트, 집합, 딕셔너리 등이 있습니다.
- 불가변 ( immutable ) : 객체의 값을 수정 불가능합니다. 숫자형, bool, 문자열, 튜플 등이 있습니다.
>>> def test( num, list ) :
num = num + 1
list.append( 10 )
return num, list>>> x = 10
>>> y = [1,2,3]
>>> test( x, y )
(11, [1, 2, 3, 10])
>>> print(x)
10
## 인자로 전달한 리스트 y 도 10이 추가되었습니다.
>>> print(y)
[1, 2, 3, 10]
>>>
위 예제 함수에 id() 를 사용하여 파이썬에서 할당한 주소를 출력해 보았습니다.
참고로 id 값은 파이썬에서 할당한 주소이고 실제 메모리 주소는 아닙니다.
C 언어를 하신 분들은 메모리 주소를 반환해 주어 혼동 될 수 있습니다.
아래 예제에서 보면 불가변객체인x 는 함수 내부에서 사용하는 id값이 다르지만, 가변 객체의 경우는 함수 내부에서 사용하는 id값이 일치 합니다.
즉, 가변객체일 경우 주소 값을 인자로 넘겨 줍니다.
따라서 원래 가지고 있던 변수도 영향을 받습니다.
>>> x = 10
>>> y = [1, 2, 3]
>>> id(x)
140719880460224
>>> id(y)
2063030421760
>>> def test( num, list ) :
num = num + 1
print('num: ', id( num ) )
list.append( 10 )
print( 'list: ', id( list) )
return num, list
>>> test( x, y )
num: 140719880460256
list: 2063030421760
(11, [1, 2, 3, 10])
>>>
그럼 전달하는 리스트 인자가 영향을 받지 않도록 하려면 어떻게 해야 할까요?
Id값이 새롭게 만들어지게 하면 됩니다.
새로 리스트를 하나 할당합니다.
아래는 deepcopy() 를 사용하여 list1을 할당하였습니다.
그래서 인자로 넘겨준 리스트 y는 영향을 받지 않았습니다.
>>> import copy
>>> x = 10
>>> y = [1, 2, 3]
>>> def test( num, list ) :
num = num + 1
list1 = copy.deepcopy( list )
list1.append( 10 )
return num, list1
>>> test( x, y )
(11, [1, 2, 3, 10])
>>> print(y)
[1, 2, 3]
>>> print(x)
10
주소값이 어떻게 할당되는지 알기 위해 위와 동일한 예제를 주소 값을 출력해 보았습니다.
deepcopy() 로 새로운 주소가 할당되었음을 알 수 있습니다.
따라서 영향을 미치지 않은 것입니다.
>>> x = 10
>>> y = [1,2,3]
>>> id(y)
2063030421760
>>> deftest( num, list ) :
num = num + 1
list1 = copy.deepcopy( list )
print( 'ID list1: ', id(list1 ) )
list1.append( 10 )
returnnum, list1
>>> test( x, y )
ID list1: 2063030071680
(11, [1, 2, 3, 10])
>>> print(y)
[1, 2, 3]
>>> id(y)
2063030421760
>>>
함수에서 가변 객체 인자를 전달할 경우 알아야 할 점에 대해 포스팅해 보았습니다.