파이썬에서의 변경 가능성과 변경 불가능성

파이썬에서의 변경 가능성과 변경 불가능성

이 글은 파이썬에서의 변경 가능성과 변경 불가능성에 대해 설명합니다.

YouTube Video

파이썬에서의 변경 가능성과 변경 불가능성

"변경 가능성(mutable)"과 "변경 불가능성(immutable)"은 객체의 변경 가능성을 의미합니다. 이를 이해하면 예상하지 못한 버그를 방지하고 효율적인 메모리 관리에 도움이 됩니다.

변경 가능성이란 무엇인가요?

변경 가능한 객체는 생성된 후에 내부 상태를 변경할 수 있습니다.

주요 변경 가능한 데이터 타입

  • list
  • dict
  • set
  • 사용자 정의 클래스 (속성을 수정할 수 있는 경우)

예시: 리스트 수정하기

1numbers = [1, 2, 3]
2numbers[0] = 100
3print(numbers)  # [100, 2, 3]

리스트는 변경 가능한 객체로, 요소를 자유롭게 수정할 수 있습니다.

변경 불가능성이란 무엇인가요?

변경 불가능한 객체한 번 생성되면 변경할 수 없습니다. 이를 수정하려고 시도하면 새 객체가 생성됩니다.

주요 변경 불가능한 데이터 타입

  • int
  • float
  • str
  • tuple
  • bool
  • frozenset

예시: 문자열 수정하기

1text = "hello"
2# text[0] = "H"  # TypeError: 'str' object does not support item assignment
3
4text = "H" + text[1:]  # Creates a new string
5print(text)  # "Hello"

문자열은 변경 불가능하여, 부분적으로 수정할 수 없습니다.

변경 가능성과 변경 불가능성의 비교

 1# Mutable example
 2a = [1, 2, 3]
 3b = a
 4b[0] = 100
 5print(a)  # [100, 2, 3] -> a is also changed
 6
 7# Immutable example
 8x = 10
 9y = x
10y = 20
11print(x)  # 10 -> x is unchanged

위의 예시에서 보시다시피, 변경 가능한 객체는 참조에 의해 공유되므로, 다른 변수에 영향을 미칠 수 있습니다. 반면, 불변 객체는 재할당 시 새로운 인스턴스를 생성하여 원래 값은 영향을 받지 않습니다.

id()를 사용하여 내부 동작 검사하기

Python에서는 id() 함수를 사용하여 객체의 ID를 확인할 수 있습니다. 객체 ID는 메모리 주소와 유사합니다.

 1# Immutable int behavior
 2a = 10
 3print(id(a))  # e.g., 140715920176592
 4a += 1
 5print(id(a))  # e.g., 140715920176624 -> ID has changed
 6
 7# Mutable list behavior
 8b = [1, 2, 3]
 9print(id(b))  # e.g., 2819127951552
10b.append(4)
11print(id(b))  # Same ID -> only the content has changed

보시다시피, 불변 타입(immutable types)에 대해서는 새로운 객체가 생성되는 반면에, 가변 타입(mutable types)은 제자리에서 수정됩니다.

함수와 변경 가능한 객체 및 불변 객체 사용 시 주의점

변경 가능한 객체를 함수에 전달할 경우, 원래 데이터가 수정될 수 있습니다.

예: 리스트를 수정하는 함수

1def modify_list(lst):
2    lst.append(100)
3
4my_list = [1, 2, 3]
5modify_list(my_list)
6print(my_list)  # [1, 2, 3, 100]

예: 숫자를 수정하는 함수

반면, 불변 객체를 수정하려고 하면 새로운 객체가 생성됩니다.

1def modify_number(n):
2    n += 10
3
4my_number = 5
5modify_number(my_number)
6print(my_number)  # 5 -> unchanged

실제 고려 사항

기본 인수로 변경 가능한 객체 사용을 피하세요

 1# Bad example
 2def add_item(item, container=[]):
 3    container.append(item)
 4    return container
 5
 6print(add_item(1))  # [1]
 7print(add_item(2))  # [1, 2] -> unintended behavior
 8
 9# Good example
10def add_item(item, container=None):
11    if container is None:
12        container = []
13    container.append(item)
14    return container

기본 인수는 함수 정의 시 한 번만 평가되기 때문에, 변경 가능한 객체를 사용하면 예기치 않은 부작용이 발생할 수 있습니다.

요약

Python의 변수와 데이터 유형을 깊이 이해하려면, 변경 가능성과 불변성의 차이를 이해하는 것이 중요합니다. 이러한 특성을 이해하면, 코드에서 의도하지 않은 동작을 방지하고 더 견고하고 읽기 쉬운 프로그램을 작성할 수 있습니다.

위의 기사를 보면서 Visual Studio Code를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.

YouTube Video