? 一、is和==的區(qū)別??二、延伸問(wèn)題?三、*和**區(qū)別?
創(chuàng)新互聯(lián)企業(yè)建站,10年網(wǎng)站建設(shè)經(jīng)驗(yàn),專(zhuān)注于網(wǎng)站建設(shè)技術(shù),精于網(wǎng)頁(yè)設(shè)計(jì),有多年建站和網(wǎng)站代運(yùn)營(yíng)經(jīng)驗(yàn),設(shè)計(jì)師為客戶打造網(wǎng)絡(luò)企業(yè)風(fēng)格,提供周到的建站售前咨詢和貼心的售后服務(wù)。對(duì)于網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)中不同領(lǐng)域進(jìn)行深入了解和探索,創(chuàng)新互聯(lián)在網(wǎng)站建設(shè)中充分了解客戶行業(yè)的需求,以靈動(dòng)的思維在網(wǎng)頁(yè)中充分展現(xiàn),通過(guò)對(duì)客戶行業(yè)精準(zhǔn)市場(chǎng)調(diào)研,為客戶提供的解決方案。
為什么會(huì)這樣呢?
小整數(shù)池目的:節(jié)省內(nèi)存,提高執(zhí)行效率。
Python中的一切東西皆為對(duì)象,那么每次給變量賦值是不是都需要新建一個(gè)對(duì)象呢?
實(shí)際編程過(guò)程中,像1、3、5這樣的整數(shù)的使用頻率比整數(shù)10000、11000使用更為頻繁,對(duì)于低頻整數(shù)每次都創(chuàng)建空間可能對(duì)于程序的性能影響并不大,但是對(duì)于較小的整數(shù),由于其使用頻率非常高,所以每次申請(qǐng)賦值都需要為其分配一個(gè)新的空間,無(wú)疑會(huì)大大降低程序的效率。
對(duì)于這個(gè)問(wèn)題,Python明智地將整數(shù)分成了小整數(shù)和大整數(shù)兩種類(lèi)型,對(duì)于兩種不同類(lèi)型的數(shù)據(jù)分別采取了不同的方案:
小整數(shù):將這部分有限的整數(shù)緩存于內(nèi)存中,可共享。
大整數(shù):將其放入使用單鏈表維護(hù)的對(duì)象池中,非共享,即每次創(chuàng)建都需要為其分配一塊新的內(nèi)存,即使內(nèi)存中已經(jīng)存在相同的整數(shù)。
需要注意的是:Python實(shí)現(xiàn)int的時(shí)候有個(gè)小整數(shù)池。為了避免因創(chuàng)建相同的值而重復(fù)申請(qǐng)內(nèi)存空間所帶來(lái)的效率問(wèn)題, Python解釋器會(huì)在啟動(dòng)時(shí)創(chuàng)建出小整數(shù)池,范圍是[-5,256]。
該范圍內(nèi)的小整數(shù)對(duì)象是全局解釋器范圍內(nèi)被重復(fù)使用,永遠(yuǎn)不會(huì)被垃圾回收機(jī)制回收。
另外創(chuàng)建變量的值如果相同的話,創(chuàng)建的時(shí)間間隔又比較短,那么他們的內(nèi)存空間的值是相同的。
在Pycharm中運(yùn)行Python程序時(shí),Pycharm出于對(duì)性能的考慮,會(huì)擴(kuò)大小整數(shù)池的范圍,其他的字符串等不可變類(lèi)型也都包含在內(nèi)一便采用相同的方式處理了,我們只需要記住這是一種優(yōu)化機(jī)制,至于范圍到底多大,無(wú)需細(xì)究。
單個(gè)* 號(hào):1.表示乘號(hào);2.表示倍數(shù);3.(1) 單個(gè)*表示接受任意多個(gè)參數(shù)并將其放在一個(gè)元組中 ;(2)函數(shù)在調(diào)用多個(gè)參數(shù)時(shí),在列表、元組、集合、字典及其他可迭代對(duì)象作為實(shí)參,并在前面加 *
如 *(1,2,3)解釋器將自動(dòng)進(jìn)行解包然后傳遞給多個(gè)單變量參數(shù)(參數(shù)個(gè)數(shù)要對(duì)應(yīng)相等)。
兩個(gè)*號(hào):
用于接收類(lèi)似于 關(guān)鍵參數(shù) 一樣賦值的形式的多個(gè)實(shí)參放入字典中(即把該函數(shù)的參數(shù)轉(zhuǎn)換為字典)。
簡(jiǎn)單來(lái)說(shuō),python中的is與is not運(yùn)算符可判斷兩個(gè)對(duì)象是否為同一對(duì)象。
若為同一個(gè)對(duì)象,則對(duì)象1 is 對(duì)象2為T(mén)rue 。
反正,若非同一個(gè)對(duì)象,則對(duì)象1 is not 對(duì)象2為T(mén)rue
要理解Python中的is和is not運(yùn)算符,首先需要知道Python中對(duì)象包含的三個(gè)基本要素,分別是:id(身份標(biāo)識(shí))、python type()(數(shù)據(jù)類(lèi)型)和value(值)。
is和==(is not和!=)都是對(duì)對(duì)象進(jìn)行比較判斷作用的。
但對(duì)對(duì)象比較判斷的內(nèi)容并不相同。
拿is和==為例,
==是python標(biāo)準(zhǔn)操作符中的比較操作符,用來(lái)比較判斷兩個(gè)對(duì)象的value(值)是否相等,例如下面兩個(gè)字符串間的比較:
a = 'iplaypython.com'
b = 'iplaypython.com'
a == b
True
is也被叫做同一性運(yùn)算符,這個(gè)運(yùn)算符比較判斷的是對(duì)象間的唯一身份標(biāo)識(shí),也就是id是否相同。通過(guò)對(duì)下面幾個(gè)列表間的比較,你就會(huì)明白is同一性運(yùn)算符的工作原理:
x = y = [4,5,6]
z = [4,5,6]
x == y
True
x == z
True
x is y
True
x is z
False
print id(x)
3075326572
print id(y)
3075326572
print id(z)
3075328140
可看出前三個(gè)例子都是True,而最后一個(gè)是False。
x、y和z的值是相同的,所以前兩個(gè)是True沒(méi)有問(wèn)題。
至于最后一個(gè)為什么是False,看看三個(gè)對(duì)象的id分別是什么就會(huì)明白了。
==比較操作符:用來(lái)比較兩個(gè)對(duì)象是否相等,value做為判斷因素;
is同一性運(yùn)算符:比較判斷兩個(gè)對(duì)象是否相同,id做為判斷因素。
同理,
!=比較操作符:用來(lái)比較兩個(gè)對(duì)象是否不等,value做為判斷因素;
is not同一性運(yùn)算符:比較判斷兩個(gè)對(duì)象是否不同,id做為判斷因素。
文件對(duì)象(open() 函數(shù)的返回值)提供了read()函數(shù)可以按字節(jié)或字符讀取文件內(nèi)容,到底是讀取字節(jié)還是字符,取決于使用 open() 函數(shù)打開(kāi)文件時(shí),是否使用了 b 模式,如果使用了 b 模式,則每次讀取一個(gè)字節(jié);反之,則每次讀取一個(gè)字符。
read() 函數(shù)的基本語(yǔ)法格式如下:
file.read([size])
其中,file 表示打開(kāi)的文件對(duì)象;size 作為一個(gè)可選參數(shù),用于指定要讀取的字符個(gè)數(shù),如果省略,則默認(rèn)一次性讀取所有內(nèi)容。
【例 1】采用循環(huán)讀取整個(gè)文件的內(nèi)容。
# a.txt 文件內(nèi)容為:C語(yǔ)言中文網(wǎng)
f = open("a.txt", 'r', True)
while True:
# 每次讀取一個(gè)字符
ch = f.read(1)
# 如果沒(méi)有讀到數(shù)據(jù),跳出循環(huán)
if not ch:
break
# 輸出ch
print(ch, end='')
f.close()
運(yùn)行結(jié)果為:
C語(yǔ)言中文網(wǎng)
上面程序采用循環(huán)依次讀取每一個(gè)字符(因?yàn)槌绦驔](méi)有使用 b 模式),每讀取到一個(gè)字符,程序就輸出該字符。
正如從上面程序所看到的,當(dāng)程序讀寫(xiě)完文件之后,推薦立即調(diào)用 close() 方法來(lái)關(guān)閉文件,這樣可以避免資源泄露(后續(xù)章節(jié)會(huì)詳細(xì)介紹 close() 函數(shù))。
注意,在調(diào)用 read() 函數(shù)讀取文件內(nèi)容時(shí),成功讀取的前提是在 open() 函數(shù)中使用 r 或 r+ 的模式打開(kāi)文件,否則(比如將上面程序中 open()的打開(kāi)模式改為 w),程序會(huì)拋出io.UnsupportedOperation異常:
Traceback (most recent call last):
File "C:\Users\mengma\Desktop\demo.py", line 4, in
ch = f.read(1)
io.UnsupportedOperation: not readable
【例 2】調(diào)用 read() 方法時(shí)不傳入?yún)?shù),該方法默認(rèn)會(huì)讀取全部文件內(nèi)容。例如:
f = open("a.txt", 'r', True)
# 直接讀取全部文件
print(f.read())
f.close()
運(yùn)行結(jié)果為:
C語(yǔ)言中文網(wǎng)
read()函數(shù)拋出UnicodeDecodeError異常的解決方法
當(dāng)使用 open() 函數(shù)打開(kāi)文本文件時(shí),默認(rèn)會(huì)使用當(dāng)前操作系統(tǒng)的字符集,比如 Windows 平臺(tái),open() 函數(shù)默認(rèn)使用 GBK 字符集。因此,上面程序讀取的 a.txt 也必須使用 GBK 字符集保存;否則,程序就會(huì)出現(xiàn)UnicodeDecodeError錯(cuò)誤。
如果要讀取的文件所使用的字符集和當(dāng)前操作系統(tǒng)的字符集不匹配,則有兩種解決方式:
使用二進(jìn)制模式讀取,然后用 bytes 的 decode() 方法恢復(fù)成字符串。
利用 codecs 模塊的 open() 函數(shù)來(lái)打開(kāi)文件,該函數(shù)在打開(kāi)文件時(shí)允許指定字符集。
例如,下面程序使用二進(jìn)制模式來(lái)讀取文本文件:
# 指定使用二進(jìn)制方式讀取文件內(nèi)容,a.txt 以 utf-8 編碼存儲(chǔ)
f = open("a.txt", 'rb', True)
# 直接讀取全部文件,并調(diào)用bytes的decode將字節(jié)內(nèi)容恢復(fù)成字符串
print(f.read().decode('utf-8'))
f.close()
上面程序在調(diào)用 open() 函數(shù)時(shí),傳入了 rb 模式,這表明采用二進(jìn)制模式讀取文件,此時(shí)文件對(duì)象的 read() 方法返回的是 bytes 對(duì)象,程序可調(diào)用 bytes 對(duì)象的 decode() 方法將它恢復(fù)成字符串。由于此時(shí)讀取的 a.txt 文件是以 UTF-8 的格式保存的,因此程序需要使用 decode() 方法恢復(fù)字符串時(shí)顯式指定使用 UTF-8 字符集。
下面程序使用 codes 模塊的 open() 函數(shù)來(lái)打開(kāi)文件,此時(shí)可以顯式指定字符集:
import codecs
# 指定使用utf-8 字符集讀取文件內(nèi)容
f = codecs.open("a.txt", 'r', 'utf-8', buffering=True)
while True:
# 每次讀取一個(gè)字符
ch = f.read(1)
# 如果沒(méi)有讀取到數(shù)據(jù),則跳出循環(huán)
if not ch : break
# 輸出ch
print (ch, end='')
f.close()
上面程序在調(diào)用 open() 函數(shù)時(shí)顯式指定使用 UTF-8 字符集,這樣程序在讀取文件內(nèi)容時(shí)就完全沒(méi)有問(wèn)題了。