新聞中心
嘗試解決以下問題,然后檢查以下答案。

公司主營(yíng)業(yè)務(wù):成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。創(chuàng)新互聯(lián)推出烏蘇免費(fèi)做網(wǎng)站回饋大家。
提示:所有問題都有共同點(diǎn),因此在解決其余問題之前檢查第一個(gè)問題的解決方案可以減輕挑戰(zhàn)。
問題1
假設(shè)我們有幾個(gè)變量:
- x = 1
- y = 2
- l = [x, y]
- x += 5
- a = [1]
- b = [2]
- s = [a, b]
- a.append(5)
l和s的打印結(jié)果是什么?
跳到解決方案
問題2
讓我們定義一個(gè)簡(jiǎn)單的函數(shù):
- def f(x, s=set()):
- s.add(x) print(s)
如果您決定,將會(huì)發(fā)生什么:
- >>f(7)
- >>f(6, {4, 5})
- >>f(2)
- ?
跳到解決方案
問題3
讓我們定義兩個(gè)簡(jiǎn)單的函數(shù):
- def f():
- l = [1]
- def inner(x):
- l.append(x)
- return l
- return inner
- def g():
- y = 1
- def inner(x):
- y += x
- return y
- return inner
以下命令將產(chǎn)生什么結(jié)果?
- >>ff_inner = f()
- >>print(f_inner(2))
- >>gg_inner = g()
- >>print(g_inner(2))
跳到解決方案
您對(duì)自己的回答有多自信? 讓我們看看您是否正確。
解決問題1
- >>print(l)
- [1, 2]
- >>print(s)
- [[1, 5], [2]]
為什么第二個(gè)列表對(duì)第一個(gè)元素a.append(5)的更改有反應(yīng),但是第一個(gè)列表完全忽略x + = 5的類似變化?
解決問題2
讓我們看看發(fā)生了什么:
- >>f(7){7}
- >>f(6, {4, 5}){4, 5, 6}
- >>f(2){2, 7}
等待,最后輸出不是{2}嗎?
解決問題3
輸出將是以下內(nèi)容:
- >>ff_inner = f()
- >>print(f_inner(2))[1, 2]
- >>gg_inner = g()
- >>print(g_inner(2))
- UnboundLocalError: local variable 'y' referenced before assignment
為什么g_inner(2)不輸出3? f()的內(nèi)部函數(shù)如何記住其外部范圍,而g()的內(nèi)部函數(shù)卻不記得呢? 它們實(shí)際上是相同的!
說明
如果我告訴您這些怪異的行為與Python中可變對(duì)象和不可變對(duì)象之間的區(qū)別有關(guān)怎么辦?
諸如列表,集合或字典之類的可變對(duì)象可以在適當(dāng)位置進(jìn)行更改(變異)。 不變的對(duì)象(如整數(shù),字符串和元組)不能—此類對(duì)象的"更改"會(huì)導(dǎo)致創(chuàng)建新對(duì)象。
問題1的說明
- x = 1
- y = 2
- l = [x, y]
- x += 5
- a = [1]
- b = [2]
- s = [a, b]
- a.append(5)
- >>print(l)
- [1, 2]
- >>print(s)
- [[1, 5], [2]]
由于x是不可變的,因此操作x + = 5不會(huì)更改原始對(duì)象,而是創(chuàng)建一個(gè)新對(duì)象。 列表的第一個(gè)元素仍指向原始對(duì)象,因此其值保持不變。
對(duì)于可變對(duì)象a,a.append(5)更改原始對(duì)象,因此list s"看到"更改。
問題2的解釋
- def f(x, s=set()):
- s.add(x)
- print(s)
- >>f(7)
- {7}
- >>f(6, {4, 5})
- {4, 5, 6}
- >>f(2)
- {2, 7}
前兩個(gè)輸出完全有意義:首先將值7添加到默認(rèn)空集中,得到{7},然后將值6添加到一組{4,5}中,得到{4,5,6 }。
但是隨后發(fā)生了一件奇怪的事情:將值2添加到默認(rèn)的空集而不是添加到{7}的集。 為什么? 可選參數(shù)s的默認(rèn)值僅被評(píng)估一次-僅在第一次調(diào)用s期間將被初始化為空集。 由于s在調(diào)用f(7)之后是可變的,因此就地進(jìn)行了修改。 第二個(gè)調(diào)用f(6,{4,5})不會(huì)影響默認(rèn)參數(shù)-提供的集合{4,5}將其遮蔽,換句話說,{4,5}是一個(gè)不同的變量。 第三次調(diào)用f(2)使用的是與第一次調(diào)用相同的s變量,但是s未作為空集重新初始化-使用了其先前的值{7}。
這就是為什么您不應(yīng)該使用可變的默認(rèn)參數(shù)的原因。 在這種情況下,應(yīng)按以下方式修改功能:
- def f(x, s=None):
- if s is None:
- s = set()
- s.add(x)
- print(s)
問題3的解釋
- def f():
- l = [1]
- def inner(x):
- l.append(x)
- return l
- return inner
- def g():
- y = 1
- def inner(x):
- y += x
- return y
- return inner
- >>ff_inner = f()
- >>print(f_inner(2))
- [1, 2]
- >>gg_inner = g()
- >>print(g_inner(2))
- UnboundLocalError: local variable ‘y’ referenced before assignment
在這個(gè)問題中,我們處理閉包-內(nèi)部函數(shù)記住定義時(shí)它們的封閉名稱空間的外觀。 或至少應(yīng)該如此-第二個(gè)功能保持撲克面孔,就像從未聽說過其外部作用域一樣。
這是為什么? 當(dāng)我們執(zhí)行l(wèi).append(x)時(shí),在定義時(shí)創(chuàng)建的可變對(duì)象被修改,但是變量l仍然指向內(nèi)存中的相同地址。 但是,嘗試更改第二個(gè)函數(shù)y + = x中的不可變變量會(huì)導(dǎo)致y指向內(nèi)存中與以前不同的地址-原始y將不再被記住,因此導(dǎo)致UnboundLocalError。
結(jié)論
Python中可變對(duì)象與不可變對(duì)象之間的區(qū)別非常重要。 請(qǐng)注意這一點(diǎn),以避免出現(xiàn)本文所述的奇怪行為。 特別是:
- 不要使用可變的默認(rèn)參數(shù)。
- 不要嘗試在內(nèi)部函數(shù)中更改不可變的閉包變量。
- 請(qǐng)隨意分享其他示例,這些示例可能是由于您在響應(yīng)中誤用了可變的和不變的對(duì)象而導(dǎo)致的潛在問題。
名稱欄目:您能解決這3個(gè)(看似)簡(jiǎn)單的Python問題嗎?
標(biāo)題路徑:http://m.fisionsoft.com.cn/article/djhscpd.html


咨詢
建站咨詢
