[python] 함수 인자가 가변 객체를 받는 경우

단간단간·2024년 5월 16일
0
post-thumbnail

⎷ 불변 객체 vs 가변 객체

불변 객체(immutable object) 설명

  • 불변 객체란?
    생성 후에는 내부 상태를 변경할 수 없는 객체이다.

  • 종류:

    • 숫자형: int, float 등등
    • 문자열: str
    • 튜플: tuple
    • fronzenset
  • 예시:

    a = 10
    a = 20  # 새로운 객체를 할당, 이전 객체는 변경되지 않음
    
    b = "hello"
    b = "world"  # 새로운 문자열 객체가 생성되고 b가 이를 참조하게 됨
    
    c = (1, 2, 3)
    # c[0] = 10  # 튜플은 불변 객체이므로 변경 불가, 이는 에러를 발생시킴

    python의 id 함수는 객체의 주소를 반환한다. 처음 객체를 할당받을 때와 새로운 객체를 할당 받을때 id값을 확인해보면 각각 다른것을 확인할 수 있는데, 이는 내부 상태를 변경한 것이 아니라 다른 객체를 새로 참조한 것으로 보면 된다. (a를 예로 들면 10이라는 값 자체를 변경한 것이 아니라, 20 이라는 값으로 참조를 변경한 것을 보면 된다.)


가변 객체(mutable object) 설명

  • 가변 객체란?
    생성 후에도 내부 상태를 변경할 수 있는 객체이다.

  • 종류:

    • 리스트: list
    • 딕셔너리: dict
    • 집합: set
  • 예시:

    a = [1, 2, 3]
    a[0] = 10  # 리스트의 첫 번째 요소를 10으로 변경
    
    b = {'key1': 'value1'}
    b['key2'] = 'value2'  # 딕셔너리에 새로운 키-값 쌍을 추가
    
    c = {1, 2, 3}
    c.add(4)  # 세트에 새로운 요소 추가

    수정 전과 후의 객체 id 값을 확인하면 동일하다. 이는 해당 객체의 내부 상태값을 변경한 것이다.


⎷ 함수 인자가 가변 객체를 받는 경우에 대하여

예시:

def solution(local_list):
    # 인자로 받은 가변 객체의 상태를 변경
    local_list[0] = 100


global_list = [1, 2, 3, 4, 5]
solution(global_list)

global_list를 호출할 경우 어떤 값이 나오는가?

print(global_list)

# 1) [1, 2, 3, 4, 5] 
# 2) [100, 2, 3, 4, 5]

정답은 2) [100, 2, 3, 4, 5]


설명:

변경한 것은 로컬 변수인 local_list 인데, 왜 외부에 있는 global_list 변수가 영향을 받은 것인가? 이는, 함수의 인자로 가변 변수를 받았기 때문이다.

  • 참조에 의한 전달:
    • 파이썬에서 리스트와 같은 가변 객체는 함수의 인자로 전달될 때 객체의 참조(reference)가 전달된다. 즉, 함수 안에서 인자로 받은 리스트(=local_list)는 원래의 리스트(=global_list)를 가리킨다.
  • 참조를 통한 변경:
    • solution(global_list)를 호출하면 global_list의 참조가 solution 함수의 매개변수 local_list로 전달된다. 이로 인해 global_listlocal_list가 같은 리스트를 참조하게 되는 것이다. (id값 동일)
    • 즉, local_list[0] = 100 으로 변경하는 것은 실제로 global_list[0]을 변경하는 것과 같다.

요약:

파이썬의 리스트와 같은 가변 객체는 함수에 전달될 때 참조에 의해 전달되므로, 함수 내부에서 리스트의 요소를 변경하면 원래 리스트에도 그 변경이 반영된다.


인자로 받은 원래의 리스트를 변경하지 않고, 새로운 리스트를 반환하도록 하려면?

파이썬에서 함수가 인자로 받은 리스트를 변경하지 않고 새로운 리스트를 반환하도록 하려면, 리스트의 복사본을 생성한 후 해당 복사본을 수정하고 반환하면 된다. 이를 통해 원본 리스트는 변경되지 않고, 수정된 새 리스트를 얻을 수 있다.

def solution(local_list):
    # 인자로 받은 가변 객체의 상태를 변경
    local_list = local_list.copy()
    local_list[0] = 100


global_list = [1, 2, 3, 4, 5]
solution(global_list)

print(global_list)
# output

[1, 2, 3, 4, 5]

가변 객체의 구조에 따라, 얕은 복사가 아닌 깊은 복사를 사용해야 한다.

profile
simple is best

0개의 댓글