파이썬에 대한 기본적인 이해를 위해 작성했습니다
int 객체의 '값'은 절대로 바뀔 수 없다.
#3 Variable Re-Assignment
변수에 값 재할당하는 경우, 변수가 참조하는 주소의 int 객체 값이 바뀌는 것이 아니라 새로 생성된 int 객체의 주소를 참조하게 된다.
예를 들어서 다음과 같이 변수에 두 번 값을 할당해 보자.
my_var = 10
my_var = my_var + 5
변수는 처음에 10이라는 값을 가진 int 객체가 저장된 주소 0x1000(예를 들어서)를 참조하게 된다.
다음에는 15라는 값을 가진 int 객체자 저장된 주소 0x1234(예를 들어서)를 참조하게 된다.
즉, 10이 저장된 주소 0x1000에 존재하는 int 객체의 값이 바뀌는 것이 아니라 15라는 값을 가진 int 객체가 저장된 주소를 가리킨다는 뜻이다.
그러면 주소 0x1000의 레퍼런스 카운트는 0이 될 것이고, 파이썬은 해당 메모리를 반환할 것이다.
흠.. 그러면 다음의 경우에는 어떨까?
my_var_1 = 10
my_var_2 = 10
두 변수가 참조하는 메모리의 주소는 다를까 같을까?
놀랍게도 같은 주소를 가리킨다.
값이 10인 int 객체 하나를 두 변수가 참조하게 되는 것이다.
이 경우 우리가 my_var_1 = 15와 같이 재할당하면 어떻게 될까?
1. my_var_2의 값도 15로 바뀐다.
2. my_var_1이 새로운 객체의 주소를 참조한다.
정답은 2. my_var_1이 새로운 객체의 주소를 참조한다.이다.
my_var 변수의 상황에서 지켜본 것과 같이, 정수 객체는 값이 바뀌지 않는다.
결국 새로운 정수 객체를 참조할 뿐이다.
파이썬은 왜 이럴까?
#4 Object Mutability
정수 데이터 객체와 다르게 특정 파이썬 내장 객체 타입( 데이터 타입 )들은 수정 가능하다.
즉, 메모리에 있는 객체의 내부 내용(상태)을 수정할 수 있다.
이렇게 내부 상태를 변경할 수 있는 객체를 Mutable이라고 한다.
반대로 정수객체와 같이 내부 상태를 변경할 수 없는 객체를 Immutable 이라고 한다.
Immutable : Numbers (int, float, Booleans, etc), Strings, Tuples, Frozen Sets, "Frozen" User-Defined Classes
Mutable : Lists, Sets, Dictionaries, User-Defined Classes
그러면, Immutable과 mutable이 같이 사용되면 어떻게 될까? 다음을 보자.
t = (1, 2, 3)
튜플은 Immutable이다. 즉, 삭제·삽입·대체가 불가능하다.
위 경우 컨테이너(튜플)와 해당 요소(정수) 둘 다 Immutable이다.
하지만 다음의 상황을 상상해 보자.
a = [1, 2]
b = [3, 4]
t = (a, b)
a.append(3)
b.append(5)
리스트는 mutable이다. 요소를 삭제·삽입·대체할 수 있다.
위 코드를 입력하면 다음 중 어떤 결과가 나올까?
1. TypeError 발생
2. t = ([1,2,3], [3,4,5]) 가 된다.
정답은 t = ([1,2,3], [3,4,5]) 가 된다.이다.
튜플은 Immutable이라고 했는데, 어째서..!
여전히 튜플은 immutable의 속성을 유지한다.
튜플의 속성이 변경되지 않았다.
튜플의 내부 상태인 리스트의 내부 상태가 변경된 것이다.
#5 Function Arguments and Mutability
대충 Immutable과 Mutable에 대해서 알 것 같다.
그러면 함수에 넘겨주는 인자들은 어떻게 작동하는지 생각해 보자.
함수에 대해서 이야기하기 전에 Scopes에 대해서 한번 보고 오자.
Python scope에 관한 정리 요약
1. Scope scope는 어떤 변수나 객체 등이 적용될 수 있는 말 그대로 범위라고 보면 된다. python에선 해당 변수나 객체가 생성된 지점에서 상위 객체까지, 아래로는 모든 하위 객체와 그 내부 까지에
smartkuma.tistory.com
Python에서 Scope란 어떤 변수나 객체 등이 적용될 수 있는 범위
Python의 scope는 L(ocal) E(nclosed function locals) G(lobal) B(uilt-in) 규칙을 따른다고 한다.
Immutable
이제 다음 코드를 보자.
def process(s):
s = s + ' world'
return s
my_var = 'hello'
process(my_var)
그러면 scopes는 두 개가 존재할 것이다.
global scope와 사용자 지정 함수 내부 local scope
이를 다음과 같이 표현하겠다.
global scope는 module scope
local scope는 process() scope
위 코드를 실행하면 다음의 순서와 같은 작동을 할 것이다.
1. module scope의 my_var가 특정 주소(0x1000이라고 가정)의 'hello'의 값을 속성으로 가지는 str객체를 참조
2. process(my_var) 호출
- 이 순간 my_var가 참조 중인 0x1000이 process() 함수에 전달된다.
- process() scope의 변수 s에 0x1000을 참조를 저장한다.
3. s = s + ' world'를 실행
- str객체는 Immutable 객체기 때문에 해당 객체의 내용을 수정할 수 없다.
- 'hello world'를 값으로 가지는 새로운 str 객체(0x1234)를 생성하여 새롭게 참조
module scope에 존재하는 my_var의 참조는 바뀌지 않았다.
process() scope에 존재하는 s의 참조가 0x1000에서 0x1234로 바뀌었다.
Immutable 객체는 의도치 않은 영향에서부터 수정 불가능함을 보장받는다
하지만 #4에서 확인한 것과 같이 Mutable 한 객체를 요소로 가지게 된다면, 요소의 수정은 가능하다.
Mutable
그러면 인자로 Mutable 객체를 넘겨보자.
def pocess(lst):
lst.append(100)
my_list = [1, 2, 3]
process(my_list)
print(my_list)
1. module scope의 my_list가 특정 주소(0x1000이라고 가정)의 list 객체를 참조
2. local 변수인 lst는 인자로 넘겨받은 0x1000을 참조
3. lst.append(100) 코드를 실행하면 lst는 참조하고 있는 메모리의 내용을 수정
- 참조하고 있는 list 객체는 Mutable 객체라서 insert가 가능
4. print(my_list)를 실행하면 [1, 2, 3, 100] 이 출력된다.
Mutable 객체는 함수에 인자로 넘겨지면, 수정될 수 있다.
#6 Shared References and Mutability
Immutable 객체는 값이 변하지 않기 때문에 Python은 같은 값의 Immutable 객체를 참조하는 경우 새로운 객체를 생성하지 않고 기존의 객체를 참조하게 한다.
예를 들어서 다음과 같이 선언된 변수는 같은 메모리 주소를 참조하게 된다.
a = 10
b = 10
만약, a가 참조하는 메모리 주소가 0x1000이라면 b가 참조하는 메모리 주소 또한 0x1000이다.
Mutable 객체는 값이 수정될 수 있다. 그렇기에 Python은 Immutable 객체의 경우와 다르게 새로운 객체를 생성하여 새로운 주소를 참조하게 한다.
예를 들어 다음과 같다.
a = [1, 2, 3]
b = [1, 2, 3]
c = a
a가 참조하는 메모리 주소가 0x1000이라고 가정하자.
b가 참조하는 주소는? 0x1000이 아닌 다른 주소가 된다(0x1234라고 가정할 수 있다).
그러면 c가 참조하는 주소는? 0x1000이 된다.
즉, c를 참조하여 수정하면, a와 같은 주소의 데이터가 수정되는 것이기 때문에 a의 값이 변경된다.
하지만, b는 다른 고유한 주소를 참조하고 있기 때문에 영향받지 않는다.
주의할 점은, Immutable 객체를 참조할 때 동일한 객체를 참조하지 않을 수도 있다.
Python이 자동으로 공유 참조를 하지만, 언제나 작동하지는 않으며 될 때도 있고 안될 때도 있다는 점을 명심해야 한다.
'TIL (Today I Learned) > Python' 카테고리의 다른 글
[Python] 변수와 메모리 (파이썬 최적화) #4 (0) | 2023.04.11 |
---|---|
[Python] 변수와 메모리 #3 (0) | 2023.04.05 |
[Python] 변수와 메모리 #1 (0) | 2023.04.03 |
[Python] Classes (0) | 2023.04.02 |
[Python] For loop (0) | 2023.04.02 |
댓글