• 2020. 7. 1.

    by. 윈썸지니

    반응형

    출처 : pixabay

     

    이전 포스팅에서 지역변수, 전역변수를 다루면서 지역 변수는 함수 안에서만 효력을 가진다고 얘기 했습니다.

    그런데 함수를 인자로 전달시 전달된 인자가 영향을 받는 부분이 있습니다.

     

    예제를 통해 알아봅니다.

    아래 함수는 숫자와 리스트를 전달하여 각 자료형에 변화를 주는 내용입니다.

    아래 예제를 보면 숫자로 선언된 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

    >>> def test( num, list ) :

        num = num + 1

        list1 = copy.deepcopy( list )

        print( 'ID list1: ', id(list1 ) )

        list1.append( 10 )

        return num, list1

    >>> test( x, y )

    ID list1:  2063030071680

    (11, [1, 2, 3, 10])

    >>> print(y)

    [1, 2, 3]

    >>> id(y)

    2063030421760

    >>>

     

    함수에서 가변 객체 인자를 전달할 경우 알아야 할 점에 대해 포스팅해 보았습니다.

    반응형