코딩하는 임초얀

Story 02. 수정 가능한 객체와 수정 불가능한 객체 본문

윤성우의 열혈 파이썬 중급편

Story 02. 수정 가능한 객체와 수정 불가능한 객체

초얀 2022. 7. 29. 02:06

이전 글 >> Story 01. 레퍼런스 카운트와 가비지 컬렉션

다음 글 >> Story 03. 깊은 복사와 얕은 복사


immutable & mutable

  • immutable 객체
    • 객체가 지닌(객체에 저장된) 값의 수정이 불가능한 객체
    • ex) 튜플, 문자열
  • mutable 객체
    • 객체가 지닌 값의 수정이 가능한 객체
    • ex) 리스트, 딕셔너리

아래 예시는 서로 비슷해보이지만 다르다.

>>> r = [1, 2]
>>> r += [3, 4]
>>> r
[1, 2, 3, 4]

>>> t = (1, 2)
>>> t += (1, 2)
>>> t
(1, 2, 3, 4)

 

객체의 주소를 반환하는 id() 함수를 이용하여 확인해볼 수 있다.

Help on built-in function id in module builtins:

id(obj, /)
    Return the identity of an object.
    
    This is guaranteed to be unique among simultaneously existing objects.
(CPython uses the object's memory address.)

 

리스트는 지니고 있는 값을 수정할 수 있다.

>>> r = [1, 2]
>>> id(r)
51637384

>>> r += [3, 4]
>>> id(r)
51637384

그러나 튜플은 값을 수정할 수 없다. 따라서 튜플에 저장된 값을 수정하게 되면 새로운 튜플이 만들어진다.

>>> t = (1, 2)
>>> id(t)
58040192

>>> t += (1, 2)
>>> id(t)
53173968

성격에 따라 달라지는 함수의 정의

리스트에 값을 추가할 때 사용하기 위해서 만든 다음 함수를 보자.

def add_last(m, n):
    m += n	# m에 n의 내용을 추가한다.

 

리스트에서는 잘 동작하지만,

>>> r = [1, 2]
>>> add_last(r, [3, 4])
>>> r
[1, 2, 3, 4]

튜플을 대상으로도 잘 동작할 것으로 기대하면 안된다.

>>> t = (1, 3)
>>> add_last(t, (5, 7))
>>> t
(1, 3)

 

이유는, 함수 내에서 진행한 += 연산 과정에서 그 결과에 해당하는 새로운 튜플이 만들어졌을 뿐 원본에 값이 추가된 것은 아니기 때문이다.

따라서, 튜플에 값을 추가한 결과를 얻는 함수는 다음과 같이 만들어야 한다.

def add_tuple(t1, t2):
    t1 += t2
    return t1

리스트는 mutable인 반면 튜플은 immutable이기 때문에 이 둘을 대상으로 동일한 결과를 보이는 함수를 만들 수 없는 경우가 있다.

이러한 경우에는 원하는 결과를 얻을 수 있는 함수를 리스트와 튜플 각각에 대해 별도로 정의해야 한다.


리스트의 최댓값과 최솟값을 출력하기 위한 다음 함수를 보자. 이를 위해서 리스트 정렬 과정을 거친다.

def min_max(d):
    d.sort()
    print(d[0], d[-1], sep=', ')

최댓값과 최솟값은 잘 출력되지만, 원본의 저장 순서가 변경된다.

>>> l = [3, 1, 5, 4]
>>> min_max(l)
1, 5
>>> l
[1, 3, 4, 5]

 

이러한 상황을 원치 않으면 함수 내에서 리스트를 복사한 다음에 정렬을 진행해야 한다.

def min_max(d):
    d = list(d)
    d.sort()
    print(d[0], d[-1], sep=', ')

원본이 수정되지 않았다.

>>> l = [3, 1, 5, 4]
>>> min_max(l)
1, 5
>>> l
[3, 1, 5, 4]

함수를 잘 정의하려면 파이썬 내에서 참조하거나 조작하는 객체의 성격을 구분하고 그에 맞게 함수를 정의해야 한다.
따라서 기본적으로 문자열과 튜플은 immutable한 객체이고, 리스트와 딕셔너리는 mutable한 객체라는 사실은 기억하고 있어야 한다.
Comments