>>> t = (0, 1, [2, 3])
>>> t[2] += [4, 5]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
여기까지는 상식적이다.
튜플은 불변 객체이므로 내부 원소에 할당을 허용하지 않는다.
-------------------------------------------------
그런데 에러를 씹고 t를 다시 참조해보면?
>>> t
(0, 1, [2, 3, 4, 5])
띠용~~
-------------------------------------------------
+=의 성질
__iadd__를 호출한다.
__iadd__가 없으면 __add__를 대신 호출하고 마치 __iadd__처럼 결과를 대입시켜준다.
불변 객체에 대해서는 __iadd__가 구현되어있어도 참조 안하고 __add__를 호출한 다음 결과값으로 새 객체를 만들어 리턴한다.
(리스트는 불변 객체가 아니나 튜플 안에 있으므로 불변인 것으로 해결될 것이다)
위에서 일어나는 일
튜플에 대한 할당 시도가 스택에 올라간다.
+= 연산이 스택에 올라간다.
+= 연산이 먼저 해결된다.(새로운 튜플을 만들어 리턴하여 t에 대입한다.)
할당 시도가 해결되어 에러가 난다.(그러나 에러의 대상은 이미 t를 떠났다.)
-------------------------------------------------
참고로 이런 건 당연히 에러도 안 뜨고 된다.
>>> t = (0, 1, [2, 3])
>>> t[2][1] += 1
>>> t
(0, 1, [2, 4])
튜플의 2번째 원소인 리스트의 값(자기 내용물의 주소범위를 가지고 있는 값) 자체는 안 건드렸기 때문에 의도 밖은 아니다.
첫번째 예제는 주소 범위 자체가 변했기 때문에 의도 외인 것이다.
신기
위에서 일어나는 일 풀어놓은 건 다시 읽어보니 설명에 오류가 있다. 내가 아직 정확히 이해하지 못했음. 암튼 큰 틀은 일어나면 안 되는 일이 그것을 제지하는 일보다 먼저 스택에서 해결된다는 것임.
ㄴ 그런 듯 ㅇㅇ