簡單來說,python中的is與is not運(yùn)算符可判斷兩個(gè)對象是否為同一對象。
專業(yè)從事企業(yè)網(wǎng)站建設(shè)和網(wǎng)站設(shè)計(jì)服務(wù),包括網(wǎng)站建設(shè)、域名注冊、雅安服務(wù)器托管、企業(yè)郵箱、微信公眾號(hào)開發(fā)、微信支付寶成都微信小程序、app軟件開發(fā)公司、軟件開發(fā)、等服務(wù)。公司始終通過不懈的努力和以更高的目標(biāo)來要求自己,在不斷完善自身管理模式和提高技術(shù)研發(fā)能力的同時(shí),大力倡導(dǎo)推行新經(jīng)濟(jì)品牌戰(zhàn)略,促進(jìn)互聯(lián)網(wǎng)事業(yè)的發(fā)展。
若為同一個(gè)對象,則對象1 is 對象2為True 。
反正,若非同一個(gè)對象,則對象1 is not 對象2為True
要理解Python中的is和is not運(yùn)算符,首先需要知道Python中對象包含的三個(gè)基本要素,分別是:id(身份標(biāo)識(shí))、python type()(數(shù)據(jù)類型)和value(值)。
is和==(is not和!=)都是對對象進(jìn)行比較判斷作用的。
但對對象比較判斷的內(nèi)容并不相同。
拿is和==為例,
==是python標(biāo)準(zhǔn)操作符中的比較操作符,用來比較判斷兩個(gè)對象的value(值)是否相等,例如下面兩個(gè)字符串間的比較:
a = 'iplaypython.com'
b = 'iplaypython.com'
a == b
True
is也被叫做同一性運(yùn)算符,這個(gè)運(yùn)算符比較判斷的是對象間的唯一身份標(biāo)識(shí),也就是id是否相同。通過對下面幾個(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沒有問題。
至于最后一個(gè)為什么是False,看看三個(gè)對象的id分別是什么就會(huì)明白了。
==比較操作符:用來比較兩個(gè)對象是否相等,value做為判斷因素;
is同一性運(yùn)算符:比較判斷兩個(gè)對象是否相同,id做為判斷因素。
同理,
!=比較操作符:用來比較兩個(gè)對象是否不等,value做為判斷因素;
is not同一性運(yùn)算符:比較判斷兩個(gè)對象是否不同,id做為判斷因素。
在python中,變量賦值的語法比較簡單,語法就是 “變量名 = 對象”,由于python屬于動(dòng)態(tài)語音,所以不需要像c、 java那樣在變量賦值時(shí)需要聲明變量的類型。
c 變量賦值
int x = 1;
python 變量賦值
x = 1
y = "hello world!"
a = [1, 2]
b = ('a', 'b')
c = {"foo": "bar"}
python 變量賦值中,所涉及到的變量命名是有一定規(guī)則的:
1. 變量名只能包含字母、數(shù)字和下劃線。變量名可以字母或下劃線開頭,但不能以數(shù)字開頭,例如,可將變量命名為name_1,但不能將其命名為1_name
2.?變量名不能包含空格,但可使用下劃線來分隔其中的單詞。例如,變量名name_one可行,但變量名name one會(huì)引發(fā)錯(cuò)誤。
3.?不要將Python關(guān)鍵字和函數(shù)名用作變量名,即不要使用Python保留用于特殊用途的單詞,如not、pass等。
4.?變量名應(yīng)既簡短又具有描述性。例如,name比n好,student_name比s_n好,name_length比length_of_persons_name好, 雖說簡短好,但是不能依照自己的意愿隨意簡寫,盡量使用大家約定俗成的簡寫,如果不是還不如寫全拼。
5. python 變量名中大小寫敏感,所以 NAME, Name, name 代表三個(gè)不同的表里名, 這里提一下就是慎用小寫字母l和大寫字母O,因給他們可能被人錯(cuò)看成數(shù)字1和0;
再說變量賦值中賦予給變量的值,python中萬事皆對象,所以python中只要是對象就能給變量賦值。如:
x = 1 # x賦值為數(shù)字1;
x = sum # x賦值為內(nèi)建求和函數(shù)sum;
python的賦值真實(shí)上說應(yīng)該不是賦值,而更像是“引用”,如何理解“引用”呢,python中一直對象的生成是會(huì)在內(nèi)存中分配給一個(gè)內(nèi)存地址,這個(gè)內(nèi)存地址可以使用id()方法去獲取,然后在變量賦值時(shí),將變量直接引用該對象的內(nèi)存地址,進(jìn)而完成變量賦值,如:
x = 1, 賦值時(shí)x直接引用1所在內(nèi)存的地址, y = x, 此時(shí)是y直接引用x的所指向的內(nèi)存地址
python中有判斷變量的方法如 is() 和 ==,二者在判斷變量時(shí)是有區(qū)別的,is函數(shù)是判斷變量的內(nèi)存地址是否相同,而 == 是判斷變量的值是否相同,舉例說明:
a = 1; b = 1.0
a is b? # False
a == b # True
小心python變量賦值的陷阱
看到上面的所述知道了python變量賦值實(shí)則是引用,引用的是對象的內(nèi)存地址。所賦的值可以分兩類,一類是可變的,如列表,字典,集合;一類是不可變的,如字符串、元組。所以當(dāng)對象為可變類型時(shí)就會(huì)出現(xiàn)一種情景,我們舉例說明:
x = [1, 2, 3]
y = x
print x == y? ? # True
print x is y? ? # True
print x? ? ?# [1, 2, 3]
print y? ? ?# [1, 2, 3]
y.append(4)
print x? ? # [1, 2, 3, 4]
print y? ? # [1, 2, 3, 4]
可以看到y(tǒng)在進(jìn)行調(diào)整時(shí)(添加了一個(gè)元素),x也跟著變動(dòng)了,這進(jìn)一步說明了,python中的變量賦值時(shí)引用,x,y 賦值時(shí)指向了同一處內(nèi)存地址,所以當(dāng)y變動(dòng)時(shí),x同樣也發(fā)送了變化,解決這中現(xiàn)象的方法可以是x, y = [1,2,3], [1,2,3]這樣賦值,雖說此時(shí) x==y 是True,但是確實(shí)是2個(gè)不同的內(nèi)存地址,所以 x is y 則是 False?;蛘呖梢允褂胏opy模塊,實(shí)質(zhì)是相同的,創(chuàng)建2個(gè)不同的內(nèi)存地址,使其分離。
文件對象(open() 函數(shù)的返回值)提供了read()函數(shù)可以按字節(jié)或字符讀取文件內(nèi)容,到底是讀取字節(jié)還是字符,取決于使用 open() 函數(shù)打開文件時(shí),是否使用了 b 模式,如果使用了 b 模式,則每次讀取一個(gè)字節(jié);反之,則每次讀取一個(gè)字符。
read() 函數(shù)的基本語法格式如下:
file.read([size])
其中,file 表示打開的文件對象;size 作為一個(gè)可選參數(shù),用于指定要讀取的字符個(gè)數(shù),如果省略,則默認(rèn)一次性讀取所有內(nèi)容。
【例 1】采用循環(huán)讀取整個(gè)文件的內(nèi)容。
# a.txt 文件內(nèi)容為:C語言中文網(wǎng)
f = open("a.txt", 'r', True)
while True:
# 每次讀取一個(gè)字符
ch = f.read(1)
# 如果沒有讀到數(shù)據(jù),跳出循環(huán)
if not ch:
break
# 輸出ch
print(ch, end='')
f.close()
運(yùn)行結(jié)果為:
C語言中文網(wǎng)
上面程序采用循環(huán)依次讀取每一個(gè)字符(因?yàn)槌绦驔]有使用 b 模式),每讀取到一個(gè)字符,程序就輸出該字符。
正如從上面程序所看到的,當(dāng)程序讀寫完文件之后,推薦立即調(diào)用 close() 方法來關(guān)閉文件,這樣可以避免資源泄露(后續(xù)章節(jié)會(huì)詳細(xì)介紹 close() 函數(shù))。
注意,在調(diào)用 read() 函數(shù)讀取文件內(nèi)容時(shí),成功讀取的前提是在 open() 函數(shù)中使用 r 或 r+ 的模式打開文件,否則(比如將上面程序中 open()的打開模式改為 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語言中文網(wǎng)
read()函數(shù)拋出UnicodeDecodeError異常的解決方法
當(dāng)使用 open() 函數(shù)打開文本文件時(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ù)來打開文件,該函數(shù)在打開文件時(shí)允許指定字符集。
例如,下面程序使用二進(jìn)制模式來讀取文本文件:
# 指定使用二進(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í)文件對象的 read() 方法返回的是 bytes 對象,程序可調(diào)用 bytes 對象的 decode() 方法將它恢復(fù)成字符串。由于此時(shí)讀取的 a.txt 文件是以 UTF-8 的格式保存的,因此程序需要使用 decode() 方法恢復(fù)字符串時(shí)顯式指定使用 UTF-8 字符集。
下面程序使用 codes 模塊的 open() 函數(shù)來打開文件,此時(shí)可以顯式指定字符集:
import codecs
# 指定使用utf-8 字符集讀取文件內(nèi)容
f = codecs.open("a.txt", 'r', 'utf-8', buffering=True)
while True:
# 每次讀取一個(gè)字符
ch = f.read(1)
# 如果沒有讀取到數(shù)據(jù),則跳出循環(huán)
if not ch : break
# 輸出ch
print (ch, end='')
f.close()
上面程序在調(diào)用 open() 函數(shù)時(shí)顯式指定使用 UTF-8 字符集,這樣程序在讀取文件內(nèi)容時(shí)就完全沒有問題了。
1、is是判斷兩個(gè)標(biāo)識(shí)符是不是引用同一個(gè)對象,類似于id(a)=id(b),如果引用的是同一個(gè)對象則返回True,否則返回False。注意python中id()函數(shù)是獲取對象的內(nèi)存地址。
2、isnot是判斷兩個(gè)標(biāo)識(shí)符是不是引用自不同對象,類似id(a)。=id(b)。如果引用的不是同一個(gè)對象則返回結(jié)果True,否則返回False。