티스토리 뷰
🚀 들어가며...
- 파이썬 사용하시다보면, 특히 복사를 하실경우 mutable과 immutable의 기본개념이 중요해집니다. 오늘은 놓치기 쉬운 개념인 python의 mutable객체와 immutable 객체에 대해 예제를 통해서 알아보겠습니다.
📑 내용
- Immutable : 숫자(number), 문자열(string), 튜플(tuple)
- Mutable : 리스트(list), 딕셔너리(dictionary), NumPy의 배열(ndarray)
즉, 숫자, 문자열, 튜플은 값을 변경하지 못하고, 리스트와 딕셔너리는 변경할 수 있다는 뜻입니다.
예시를 들어보겠습니다.
Pithon 문자열을 Python으로 바꾸려면 어떻게 해야 할까요? 보통의 경우 이렇게 먼저 생각이 떠오르실 겁니다.
>>> a = "Pithon"
>>> a[1]
'i'
>>> a[1] = 'y'
즉 a 변수에 "Pithon" 문자열을 대입하고 a[1]의 값이 i니까 a[1]을 y로 바꾸어 준다는 생각입니다. 하지만 결과는 어떻게 나올까요?
당연히 오류가 발생합니다. 왜냐하면 문자열의 요솟값은 바꿀 수 있는 값이 아니기 때문입니다(문자열 자료형은 그 요솟값을 변경할 수 없습니다. 그래서 immutable한 자료형이라고도 부릅니다).
해결책은 슬라이싱 기법을 사용하면 됩니다.
>>> a = "Pithon"
>>> a[:1]
'P'
>>> a[2:]
'thon'
>>> a[:1] + 'y' + a[2:]
'Python'
위 예에서 볼 수 있듯이 슬라이싱을 사용하면 "Pithon" 문자열을 'P' 부분과 'thon' 부분으로 나눌 수 있기 때문에 그 사이에 'y' 문자를 추가하여 'Python'이라는 새로운 문자열을 만들 수 있습니다.
숫자형식도 마찬가지로 간단한 예시로 알아보자면,
>>> x = 1
>>> y = x
>>> id(1)
140706521527120
>>> id(x)
140706521527120
>>> id(y)
140706521527120
>>> y += 3
>>> id(y)
140706521527216
y값 변경 전까지는 1이라는 동일한 객체를 x와 y가 가르키고 있지만, y의 값을 변경하는 순간 y는 4를, x는 1을 가르키게 됩니다.
다음으로 딕셔너리일때 예시를 딕셔너리의 특징과 함께 한번 보겠습니다.
먼저 딕셔너리에서 Key는 고유한 값이므로 중복되는 Key 값을 설정해 놓으면 하나를 제외한 나머지 것들이 모두 무시된다는 점을 주의해야 합니다. 다음 예에서 볼 수 있듯이 동일한 Key가 2개 존재할 경우 1:'a' 쌍이 무시됩니다.
>>> a = {1:'a', 1:'b'}
>>> a
{1: 'b'}
이렇게 Key가 중복되었을 때 1개를 제외한 나머지 Key:Value 값이 모두 무시되는 이유는 Key를 통해서 Value를 얻는 딕셔너리의 특징에서 비롯됩니다. 즉 동일한 Key가 존재하면 어떤 Key에 해당하는 Value를 불러야 할지 알 수 없기 때문입니다.
또 한 가지 주의해야 할 사항은 Key에 리스트는 쓸 수 없다는 것입니다. 하지만 튜플은 Key로 쓸 수 있습니다. 딕셔너리의 Key로 쓸 수 있느냐 없느냐는 Key가 변하는(mutable) 값인지 변하지 않는(immutable) 값인지에 달려 있습니다. 리스트는 그 값이 변할 수 있기 때문에 Key로 쓸 수 없습니다. 다음 예처럼 리스트를 Key로 설정하면 리스트를 키 값으로 사용할 수 없다는 오류가 발생합니다.
>>> a = {[1,2] : 'hi'}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
따라서 딕셔너리의 Key 값으로 딕셔너리를 사용할 수 없음은 당연합니다. 단 Value에는 변하는 값이든 변하지 않는 값이든 상관없이 아무 값이나 넣을 수 있습니다.
복사
immutable객체와 mutable객체는 복사와 깊은 관련이 있습니다.
Python에서 immutable 자료형(숫자, 문자열, 튜플)은 직접 값이 변경되는 deep copy로 이해할 수 있습니다. 반면에 mutable 자료형(즉, 쓰기가 가능한 컨테이너)는 shallow copy(내부적으로 포인터만 복사)를 적용됩니다.
하지만, mutable한 자료형도 깊은복사가 가능합니다. 예시를 통해 알아보겠습니다.
변수 a와 b가 있을경우, b 변수를 생성할 때 a 변수의 값을 가져오면서 a와는 다른 주소를 가리키도록 만들수있는 방법은 2가지가 있습니다.
1. copy 모듈 이용
>>> a = [1,2,3]
>>> b = a # b와 a는 같은 값을 가르킴(shallow copy)
>>> b is a
True
>>> b[1] = 10 # a = b = [10,11]
>>> a = [5, 11] # a = [5,11] 이도록 새로 지정함, b와 연결이 끊어짐.
>>> b is a
False
실제 값까지 복사(deep copy)하기 위해서는 object.copy() 를 사용해야 합니다.
>>> a = [1,2,3]
>>> b = a.copy()
>>> b is a
False
>>> b == a
True
위에서 is 와 ==를 통한 결과값이 다른 것을 알 수 있습니다. is는 내부적으로 유지하는 포인터값을 비교하고, ==는 list를 구성하는 성분을 비교합니다.
2. [:] 이용
>>> a = [1, 2, 3]
>>> b = a[:]
>>> a[1] = 4
>>> a
[1, 4, 3]
>>> b
[1, 2, 3]
위 예에서 볼 수 있듯이 a 리스트 값을 바꾸더라도 b 리스트에는 영향을 끼치지 않습니다.
🙋🏻♂️ 후기
오늘은 놓치기 쉬운 파이썬 자료형의 immutable 과 mutable에 대해 알아보았고, 그것과 관련깊은 복사 개념도 함께 알아보았습니다. 쉽지만 놓치기 쉬운 개념이라 잊어버릴때마다 한번씩 상기해두시는 방향이 좋은것 같습니다!
🔗 참고한 글
'Python' 카테고리의 다른 글
[python] 언더스코어(_, __) 에 대해 알아보자! (0) | 2022.06.27 |
---|---|
[python] list 정렬시 특징 정리 (0) | 2022.05.24 |
[Python] 파이썬에서 json모듈 다루는 방법 (0) | 2022.05.12 |
[Python] 클래스형 vs 함수형 둘 중에 뭐로 개발하지?? (0) | 2022.05.11 |
[Python] Join, Split 사용법 (Set 자료형과 연계하여 query문 만들기) (0) | 2022.05.11 |
- Total
- Today
- Yesterday
- django ORM
- Python
- lv1
- MVT
- Greedy Algorithm
- docker
- uSWGI
- This
- union-find
- container
- programmers
- Linux
- Named export
- Master & Slave
- django
- SQL
- lv2
- generator expression
- Default export
- JavaScript
- 탐욕법
- JS
- static files
- Algorithm
- PostgreSQL
- data formatting
- ORM
- list
- react
- db
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |