In [55]: a = 5
In [56]: b = 6
In [57]: (a, b) = (b, a)
In [58]: a
Out[58]: 6
In [59]: b
Out[59]: 5
a와 b의 값을 내부적으로 교환하는 방법은 무엇입니까? 그것은 확실히 임시 변수를 사용하지 않습니다.파이썬 튜플 (a, b) = (b, a)의 멤버를 내부적으로 교환하는 방법은 무엇입니까?
In [55]: a = 5
In [56]: b = 6
In [57]: (a, b) = (b, a)
In [58]: a
Out[58]: 6
In [59]: b
Out[59]: 5
a와 b의 값을 내부적으로 교환하는 방법은 무엇입니까? 그것은 확실히 임시 변수를 사용하지 않습니다.파이썬 튜플 (a, b) = (b, a)의 멤버를 내부적으로 교환하는 방법은 무엇입니까?
파이썬은 오른쪽 수식과 왼쪽 수식을 구분합니다. 먼저 오른쪽이 계산되고 스택에 결과가 저장되고 왼쪽에있는 이름은 값을 가진 opcode를 사용하여 할당됩니다.에서 다시 스택이됩니다.
2-3 항목 튜플 할당은가 파이썬 단지 직접 스택 사용 (스택에 변수의 값을 푸시) 두 LOAD_FAST
opcodes 후
>>> import dis
>>> def foo(a, b):
... a, b = b, a
...
>>> dis.dis(foo)
2 0 LOAD_FAST 1 (b)
3 LOAD_FAST 0 (a)
6 ROT_TWO
7 STORE_FAST 0 (a)
10 STORE_FAST 1 (b)
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
를, 스택의 상단 [a, b]
보유 . ROT_TWO
opcode은 스택의 상단 두 위치를 바꿔서 이제 스택의 상단에 [b, a]
이 있습니다. 두 STORE_FAST
opcodes은 두 값을 가져 와서 할당 왼쪽에있는 이름에 저장합니다. 첫 번째 STORE_FAST
은 스택의 최상위 값을 가져와 a
에 넣고 다음 번 다시 팝하여 b
에 값을 저장합니다. Python은 왼쪽의 대상 목록에있는 할당이 왼쪽에서 오른쪽으로 수행되도록 보장하기 때문에 회전이 필요합니다.
3 자 지정의 경우 ROT_THREE
다음에 ROT_TWO
이 실행되어 스택의 상위 3 개 항목을 뒤집습니다. 더 이상 왼손 측 할당에 대한
는 명시 적 튜플이 내장되어 있습니다 :
[d, c, b, a]
와 스택 밀어 다시 스택에서 역순으로 (
BUILD_TUPLE
팝을 튜플을 구축하는 데 사용됩니다 여기에
>>> def bar(a, b, c, d):
... d, c, b, a = a, b, c, d
...
>>> dis.dis(bar)
2 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 LOAD_FAST 2 (c)
9 LOAD_FAST 3 (d)
12 BUILD_TUPLE 4
15 UNPACK_SEQUENCE 4
18 STORE_FAST 3 (d)
21 STORE_FAST 2 (c)
24 STORE_FAST 1 (b)
27 STORE_FAST 0 (a)
30 LOAD_CONST 0 (None)
33 RETURN_VALUE
결과 집합을 스택에 놓은 다음) UNPACK_SEQUENCE
은 스택에서 다시 터플을 팝하고 STORE_FAST
작업을 위해 다시 터플에서 모든 요소를 다시 스택으로 푸시합니다.
후자는 낭비 작업처럼 보일 수 있지만, 파이썬 인터프리터는 어떠한 가정도하지 않으며 UNPACK_SEQUENCE
를 사용하므로 할당의 오른쪽이 완전히 다른 무언가, 아마도 튜플을 생성하는 함수를 호출 할 수있다 항상 opcode. 두 및 세 이름 지정 작업의 경우에도 마찬가지입니다. but a later (peephole) optimization step은 효율을 위해 위의 ROT_TWO
및 ROT_THREE
opcode로 2 또는 3 인수를 사용하여 BUILD_TUPLE
/UNPACK_SEQUENCE
조합을 바꿉니다.
+1 ** 왼쪽에있는 대상 목록의 지정이 왼쪽에서 오른쪽으로 이루어 지도록 Python에서 보장하기 때문에 회전이 필요합니다. **. 난 몰랐어. –
'확실히 임시 변수를 사용하지 않습니까? '이것은 이상한 질문입니다. 그것은 당신이 그것을 알고있는 것처럼 들린다. – RedX
['dis'] (http://docs.python.org/3/library/dis.html)를 사용하여 코드 해체를 확인하십시오. Spoliers : 바이트 코드 명령어 ['ROT_TWO'] (http://docs.python.org/2/library/dis.html#opcode-ROT_TWO)가 사용됩니다. – Kevin
@RedX : 내가 알았다면 나는이 질문을하지 않았을 것이다. 임시 변수를 사용하는 것은 스와핑에 대한 간단한 접근법입니다. – praveen