Python中對象包含的三個基本要素:id(身份標識),type(數據類型),value(值)python
x = y = [1, 2, 3] z = [1, 2, 3] print(x == y) # True print(x == z) # True print(x is y) # True print(x is z) # False print(id(x)) # 4416785008 print(id(y)) # 4416785008 print(id(z)) # 4416784504
對於整數對象,Python把一些頻繁使用的整數對象緩存起來,保存到一個叫small_ints
的鏈表中,在Python的整個生命週期內,任何須要引用這些整數對象的地方,都再也不從新建立新的對象,而是直接引用緩存中的對象。Python把這些可能頻繁使用的整數對象規定在範圍[-5, 256]之間的小對象放在small_ints
中,但凡是須要用些小整數時,就從這裏面取,再也不去臨時建立新的對象。緩存
一、當整數對象在區間[-5,256]內時,is獲得的結果是True(a,b的id值相同)函數
二、當整數對象不在區間[-5,256]內時,is獲得的結果是False(a,b的id值不一樣)性能
三、看懂上面兩個例子後,咱們接着看如下代碼:spa
c = 257 def test(): a = 257 b = 257 print(a is b) # True print(a is c) # False print(id(a)) # 140644774393856 print(id(b)) # 140644774393856 print(id(c)) # 140644774394072 test()
若是按照第2點得出的結論,257不在區間[-5,256]內,那麼兩個的is結果都應該爲False纔對,但是爲何a is b卻爲True呢?code
爲了弄清楚這個問題,首先咱們要先理解程序的代碼塊問題。Python程序由代碼塊構成,代碼塊做爲程序的一個最小基本單位來執行。一個模塊文件、一個函數體、一個類、交互式命令中的單行代碼都叫作一個代碼塊。在上面這段代碼中,由兩個代碼塊構成,c = 257
做爲一個代碼塊,函數test做爲另一個代碼塊。Python內部爲了將性能進一步的提升,凡是在一個代碼塊中建立的整數對象,若是存在一個值與其相同的對象於該代碼塊中了,那麼就直接引用,不然建立一個新的對象出來。Python出於對性能的考慮,但凡是不可變對象,在同一個代碼塊中的對象,只有是值相同的對象,就不會重複建立,而是直接引用已經存在的對象。所以,不只是整數對象,還有字符串對象也遵循一樣的原則。因此 a is b
就理所固然的返回True
了,而c
和a
不在同一個代碼塊中,所以在Python內部建立了兩個值都是257的對象。對象
注:以下圖所示,在PyCharm中運行以下代碼,獲得的結果都爲True,緣由就是由於在同一代碼塊中,值相同的對象就不會重複建立,而是直接引用已經存在的對象生命週期
a = 1 # a和b爲數值類型,在區間[-5,256]內 b = 1 print(a is b) # True print(id(a)) # 140586619260200 print(id(b)) # 140586619260200 a = 257 # a和b爲數值類型,不在區間[-5,256]內 b = 257 print(a is b) # True print(id(a)) # 140586619294392 print(id(b)) # 140586619294392
當a,b爲字符串對象時,python中有intern機制,它指的就是在建立一個新的字符串對象時,若是已經有了和它的值相同的字符串對象,那麼就直接返回那個對象的引用,而不返回新建立的字符串對象。只包括字母數字下劃線的字符串,python會對它們使用intern機制。(因此當字符串只包括字母數字下劃線時,進行is操做返回True,若是包含其餘字符,進行is操做則返回False)字符串
a = "a_1" # a和b爲字符串類型 b = "a_1" print(a is b) # True print(id(a)) # 4454524688 print(id(b)) # 4454524688 a = "&" # a和b爲字符串類型 b = "&" print(a is b) # True print(id(a)) # 4305008120 print(id(b)) # 4305008120
注:當a,b爲單個字符對象時,進行is操做都返回Truetest
當a,b爲元組,list,dict和set類型時,進行is操做結果爲False
a = (1, 2, 3) # a和b爲元組類型 b = (1, 2, 3) print(a is b) # False print(id(a)) # 4366076016 print(id(b)) # 4366076416 a = [1, 2, 3] # a和b爲list類型 b = [1, 2, 3] print(a is b) # False print(id(a)) # 4366191216 print(id(b)) # 4366190712 a = {'is' : 1, 'equal' : 2} # a和b爲dict類型 b = {'is' : 1, 'equal' : 2} print(a is b) # False print(id(a)) # 4365197952 print(id(b)) # 4366187608 a = ([1, 2, 3]) # a和b爲set類型 b = ([1, 2, 3]) print(a is b) # False print(id(a)) # 4366190712 print(id(b)) # 4366191216