https://github.com/leisurelicht/wtfPython-cn
第一個(gè):神奇的字典鍵
some_dict = {}
some_dict[5.5] = "Ruby"
some_dict[5.0] = "JAVAScript"
some_dict[5] = "Python"
Output:
>>> some_dict[5.5]
"Ruby"
>>> some_dict[5.0]
"Python"
>>> some_dict[5]
"Python"
"Python" 消除了 "JavaScript" 的存在?
說明:
-
Python 字典通過檢查鍵值是否相等和比較哈希值來確定兩個(gè)鍵是否相同.
-
具有相同值的不可變對(duì)象在Python中始終具有相同的哈希值.
注意: 具有不同值的對(duì)象也可能具有相同的哈希值(哈希沖突).
>>> 5 == 5.0
True
>>> hash(5) == hash(5.0)
True
-
當(dāng)執(zhí)行
some_dict[5] = "Python"
語句時(shí), 因?yàn)镻ython將5
和5.0
識(shí)別為some_dict
的同一個(gè)鍵, 所以已有值 "JavaScript" 就被 "Python" 覆蓋了. -
這個(gè) StackOverflow的 回答(https://stackoverflow.com/a/32211042/4354153) 漂亮的解釋了這背后的基本原理.
第二個(gè):異常處理中的return
def some_func:
try:
return 'from_try'
finally:
return 'from_finally'
Output:
>>> some_func
'from_finally'
說明:
-
當(dāng)在 "try...finally" 語句的
try
中執(zhí)行return
,break
或continue
后,finally
子句依然會(huì)執(zhí)行. -
函數(shù)的返回值由最后執(zhí)行的
return
語句決定. 由于finally
子句一定會(huì)執(zhí)行, 所以finally
子句中的return
將始終是最后執(zhí)行的語句.
第三個(gè):相同對(duì)象的判斷
class WTF:
pass
Output:
>>> WTF == WTF # 兩個(gè)不同的對(duì)象應(yīng)該不相等
False
>>> WTF is WTF # 也不相同
False
>>> hash(WTF) == hash(WTF) # 哈希值也應(yīng)該不同
True
>>> id(WTF) == id(WTF)
True
說明:
-
當(dāng)調(diào)用
id
函數(shù)時(shí), Python 創(chuàng)建了一個(gè)WTF
類的對(duì)象并傳給id
函數(shù). 然后id
函數(shù)獲取其id值 (也就是內(nèi)存地址), 然后丟棄該對(duì)象. 該對(duì)象就被銷毀了. -
當(dāng)我們連續(xù)兩次進(jìn)行這個(gè)操作時(shí), Python會(huì)將相同的內(nèi)存地址分配給第二個(gè)對(duì)象. 因?yàn)?(在CPython中)
id
函數(shù)使用對(duì)象的內(nèi)存地址作為對(duì)象的id值, 所以兩個(gè)對(duì)象的id值是相同的. -
綜上, 對(duì)象的id值僅僅在對(duì)象的生命周期內(nèi)唯一. 在對(duì)象被銷毀之后, 或被創(chuàng)建之前, 其他對(duì)象可以具有相同的id值.
-
那為什么
is
操作的結(jié)果為False
呢? 讓我們看看這段代碼.
class WTF(object):
def __init__(self): print("I")
def __del__(self): print("D")
Output:
>>> WTF is WTF
I
I
D
D
False
>>> id(WTF) == id(WTF)
I
D
I
D
True
正如你所看到的, 對(duì)象銷毀的順序是造成所有不同之處的原因.