2016-11-09 129 views
-1

有人能向我解釋爲什麼這個函數返回不同的結果:爲什麼這個函數返回不同的結果?

def g(x, z): 
    x.append(z) 
    return x 

y = [1, 2, 3] 
g(y, 4).extend(g(y[:], 4)) 

y = [1, 2, 3] 
g(y[:], 4).extend(g(y, 4)) 

第一返回

[1, 2, 3, 4, 1, 2, 3, 4, 4] 

和第二

[1, 2, 3, 4] 
+1

實際上都返回'None'。你的意思是'y'被設置爲那個值? –

+1

爲什麼你要這麼長時間才能使Python列表操作變得如此複雜? –

回答

-1

在你路過列表中的第一個電話參考,在第二次電話會議上,您製作了一份清單副本(將其列入清單)。 解釋:

>>> one = [1,2,3] 
>>> ref = one 
>>> copy = one[:] 
>>> one 
[3, 2, 3] 
>>> ref 
[3, 2, 3] 
>>> copy 
[1, 2, 3] 
0

你對作業和副本做了一個混亂。需要注意的是:

  • append()修改就地列表中,而無需創建一個新的
  • 也是如此extend()
  • y[:]並創建一個新的列表

你的表情回到None。您只對列表進行修改,不保存對新列表的引用。

讓我「展開」你的代碼,以示區別:

# First snippet: 
y = [1, 2, 3] 
y.append(4) 
y_copy = list(y) 
y_copy.append(4) 
y.extend(y_copy) 

# Second snippet: 
y = [1, 2, 3] 
y_copy = list(y) 
y_copy.append(4) 
y.append(4) 
y_copy.extend(y) 

正如你所看到的,在第二個例子中,你最適用修改到副本,而不是原來的。首先,所有更改都轉到原始。

從主觀上看,該代碼片段很難理解。你自己寫的,不能遵循它,而且我有多年的Python經驗,並且仍然需要拉開「展開」的訣竅。儘量保持代碼簡單,以便可以跟蹤和推理對象。

1

在這兩種情況下,返回None,因爲list.extend()擴展名單就地。所以你一定要看看y的結局如何。這就是摩擦的地方;在第二個例子中,你沒有擴展y本身。

在第一個例子,你基本上是這樣做:

y.append(4)   # y = [1, 2, 3, 4] 
temp_copy = y[:]  # temp_copy = [1, 2, 3, 4] 
temp_copy.append(4) # temp_copy = [1, 2, 3, 4, 4] 
y.extend(temp_copy) # y = [1, 2, 3, 4, 1, 2, 3, 4, 4] 
del temp_copy 
print(y) 

temp_copy名字從來沒有真正建立;該列表僅在堆棧中可用,並且在g()之內簡寫爲x,這就是爲什麼我在末尾再次刪除temp_copy以便清楚說明。

所以y首先附加到,然後擴展與另一個列表(這恰好是與另一個元素添加y副本)。

在你的第二個例子,你這樣做,而不是:

temp_copy = y[:] # temp_copy = [1, 2, 3] 
temp_copy.append(4) # temp_copy = [1, 2, 3, 4] 
y.append(4)   # y = [1, 2, 3, 4] 
temp_copy.extend(y) # temp_copy = [1, 2, 3, 4, 1, 2, 3, 4] 
del temp_copy 
print(y) 

你追加一個元素y,和所有其他的操作應用到副本。副本是再次丟棄,因爲在你的代碼中沒有對它的引用。

+0

啊我現在明白了,謝謝你的詳細回覆 – nihilistexistance

相關問題