代碼:x,y = y,x在Python中交換值的邏輯是什麼?
x="salil"
y="Ajay"
y,x=x,y
print x +" "+ y
輸出:
Ajay salil
,這是什麼邏輯的解釋嗎?
代碼:x,y = y,x在Python中交換值的邏輯是什麼?
x="salil"
y="Ajay"
y,x=x,y
print x +" "+ y
輸出:
Ajay salil
,這是什麼邏輯的解釋嗎?
這一機制的運作方式是兩個特徵的組合 - 形成隱元組和元組/列表解包。
當你做something = x, y
時,Python會做的是隱式地創建一個tuple(一種不可變列表),它由兩個元素x和y組成。所以,下面的代碼兩行是完全等價的:
something = x, y
something = (x, y)
的元組,當然可以,包含兩個以上要素:
something = a, b, c, d, e
something = (a, b, c, d, e)
此功能的打算用例是使其更容易/清潔劑做的事情一樣返回多個值從一個函數:
def foo():
return "hello", "world"
第二反饋eature是元組/列表開箱。每當你在左邊有一系列變量,以及任何類型的列表,元組或其他集合時,Python都會嘗試將右邊的每個元素與左邊的元素進行匹配:
>>> a, b, c = [11, 22, 33]
>>> print(a)
11
>>> print(b)
22
>>> print(c)
33
如果有幫助,行a, b, c = [11, 22, 33]
基本上等同於做:
temp = [11, 22, 33]
a = temp[0]
b = temp[1]
c = temp[2]
注意,右側可以從字面上任何類型的集合,而不只是元組或列表。所以下面的代碼是有效的:
>>> p, q = "az"
>>> print(p + " " + q)
a z
>>>
>>> s, t = {'cat': 'foo', 'dog': 'bar'}
>>> print(s + " " + t)
cat dog
(雖然,因爲在Python字典沒有義務要在任何特定的順序,而且由於鍵的順序可以自由炒,拆包他們可能不會因爲每次你都可能得到不同的結果。)
如果變量的數量和集合中的元素數量不匹配,Python會拋出異常:
>>> a, b = (1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
>>> a, b, c = (1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 2 values to unpack
因此,這意味着,如果我們從上面傳來叫我們foo
功能,做以下內容:
>>> x, y = foo()
...變量x
就等於字符串"hello"
和可變y
就等於字符串"world"
。
所以,最後,這意味着你原來的代碼片段:
x = "salil"
y = "Ajay"
y, x = x, y
...在邏輯上等同於以下內容:
x = "salil"
y = "Ajay"
temp = (x, y) # evaluates to ("salil", "Ajay")
y, x = temp
...甚至細分更多,在邏輯上等同於以下內容:
x = "salil"
y = "Ajay"
temp = (x, y) # evaluates to ("salil", "Ajay")
y = temp[0]
x = temp[1]
請注意,您可以將這兩種操作分開進行。首先形成並評估元組,然後將元組解壓縮回變量。最終結果是您的兩個變量的值互換。 (但是,事實證明,CPython解釋器(Python的原始和'標準'實現)在這裏做了一些優化:它將優化交換並且不會完成整個元組的解包 - 參見下面的評論我不確定是否Python的其他實現也是這樣做的,儘管我懷疑它們可能會這樣做。無論如何,這種優化是針對特定實現的,並且獨立於Python語言本身的設計。)
解釋器是否首先進行打包或分配? –
@salilvishnuKapur在任務發生前,總是對右手邊進行全面評估。對於Python和大多數編程語言而言,情況總是如此),而不僅僅是用元組打包/解包。 – Michael0x2a
但解釋器沒有從左到右讀取每行代碼? –
這適用於交換,因爲首先評估=
的右側。
所以在右邊,它的計算結果
'salil', 'Ajay'
,然後的x
和y
分配情況
x, y = 'salil', 'Ajay'
但解釋器不會從左到右讀取每行代碼? –
@salilvishnuKapur它*掃描*和*解析*的方式,但它不*執行*的方式。否則,運營商的優先權和事實上的分配將不可能。 – EJP
@EJP好的,謝謝!=運算符右側的 –
好吧,讓我們來看看:
import dis
src = '''
x="salil"
y="Ajay"
y,x=x,y
print x +" "+ y
'''
code = compile(src, '<string>', 'exec')
dis.dis(code)
這將產生:
2 0 LOAD_CONST 0 ('salil')
3 STORE_NAME 0 (x)
3 6 LOAD_CONST 1 ('Ajay')
9 STORE_NAME 1 (y)
4 12 LOAD_NAME 0 (x)
15 LOAD_NAME 1 (y)
18 ROT_TWO
19 STORE_NAME 1 (y)
22 STORE_NAME 0 (x)
6 25 LOAD_NAME 0 (x)
28 LOAD_CONST 2 (' ')
31 BINARY_ADD
32 LOAD_NAME 1 (y)
35 BINARY_ADD
36 PRINT_ITEM
37 PRINT_NEWLINE
38 LOAD_CONST 3 (None)
41 RETURN_VALUE
請記住,Python作爲堆棧機器運行。在這種情況下,它優化了對ROT_TWO
(即交換)指令的分配。還有一個ROT_THREE
指令。但是,讓我們嘗試別的東西:
import dis
src = 'x, y, z, w = a, b, c, d'
code = compile(src, '<string>', 'exec')
dis.dis(code)
由此產生的一般形式:
1 0 LOAD_NAME 0 (a)
3 LOAD_NAME 1 (b)
6 LOAD_NAME 2 (c)
9 LOAD_NAME 3 (d)
12 BUILD_TUPLE 4
15 UNPACK_SEQUENCE 4
18 STORE_NAME 4 (x)
21 STORE_NAME 5 (y)
24 STORE_NAME 6 (z)
27 STORE_NAME 7 (w)
30 LOAD_CONST 0 (None)
33 RETURN_VALUE
你能解釋一下這個更詳細的LOAD_FAST,LOAD_FAST,ROT_TWO嗎? –
邏輯?這就是它的工作原理。第一個右邊被分配到第一個左邊,第二個右邊被分配到第二個左邊,同時。什麼不清楚呢? – Amadan
我想知道編譯器如何讀取它,更優先於和=運算符在這裏的任何問題? –
相關:http://stackoverflow.com/questions/14836228/is-there-a-standardized-method-to-swap-two-variables-in-python – NightShadeQueen