Python 1 - 內(nèi)置類(lèi)型 - 序列(1)

Python 1 - 內(nèi)置類(lèi)型 - 序列(1)

Python 中提供了 3 種基本的序列類(lèi)型:list通孽、tuplerange。大家可能對(duì)這3中類(lèi)型都比較熟悉产弹。

一般我們認(rèn)為 tuple類(lèi)型是不可以改變的list,當(dāng)然弯囊,這在日常使用中取视,并沒(méi)有什么不對(duì)硝皂,表現(xiàn)出來(lái)的屬性也能驗(yàn)證這個(gè)說(shuō)法,但是作谭,在Python的底層實(shí)現(xiàn)當(dāng)中稽物,tuplelist 是完全不同的兩個(gè)類(lèi)型,后面我們會(huì)對(duì)他們的不同之處加以分析折欠。

語(yǔ)句range(n)大家在for in 語(yǔ)句中經(jīng)常使用贝或,一般作為index來(lái)遍歷其他類(lèi)型的迭代。我們?cè)谑褂玫臅r(shí)候一般認(rèn)為range(start, stop, step)方法產(chǎn)生了一個(gè)以start開(kāi)始锐秦,stop結(jié)束咪奖,以step為間隔的列表。但是實(shí)際上酱床,range也是一種基本的序列類(lèi)型羊赵,它也并不會(huì)返回一個(gè)我們認(rèn)為的list

可變序列

不可變序列類(lèi)型與可變序列的區(qū)別就是扇谣,可變類(lèi)型沒(méi)有實(shí)現(xiàn)對(duì) hash() 內(nèi)置函數(shù)的支持昧捷。這種對(duì)hash()的支持,可以讓 tuple作為dict的鍵存在罐寨。

list靡挥,bytearray就是可變序列。

不可變序列

不可變序列類(lèi)型的對(duì)象一旦創(chuàng)建就不能再改變:如果對(duì)象包含了對(duì)其他對(duì)象的引用鸯绿,其中的可變對(duì)象就是可改變的跋破;但是一個(gè)不可變對(duì)象所直接引用的對(duì)象集是不能改變的。

str,tuple,bytes都是不可變對(duì)象瓶蝴。相應(yīng)的不可變序列就有 tuplerange毒返,它們都是可以被hash()所使用的。

關(guān)于可變對(duì)象和不可變對(duì)象官方給出的例子舷手。

我們打算對(duì)元組的元素進(jìn)行自增運(yùn)算饿悬,所以我們使用了 +=

>>> a=(1,2)
>>> a[0] += 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

報(bào)錯(cuò)信息告訴我們聚霜,元組對(duì)象不支持元素賦值狡恬。
發(fā)生異常的原因是顯而易見(jiàn)的:

  • 1 會(huì)與對(duì)象 a_tuple[0] 相加,而該對(duì)象為 (1)蝎宇,得到結(jié)果對(duì)象 2弟劲,
  • 但當(dāng)我們?cè)噲D將運(yùn)算結(jié)果 2 賦值給元組的 0 號(hào)元素時(shí)就將報(bào)錯(cuò),因?yàn)槲覀儾荒芨淖冊(cè)M的元素所指向的對(duì)象姥芥。

在表層之處兔乞,以上增強(qiáng)賦值語(yǔ)句所做的大致是這樣:

>>> result = a_tuple[0] + 1
>>> a_tuple[0] = result
Traceback (most recent call last):
  ...
TypeError: 'tuple' object does not support item assignment

我們打算給元組中的列表元素進(jìn)行擴(kuò)展。

>>> a_tuple = (['foo'], 'bar')
>>> a_tuple[0] += ['item']
Traceback (most recent call last):
  ...
TypeError: 'tuple' object does not support item assignment

由于上面的例子,我們知道賦值會(huì)報(bào)錯(cuò)庸追,但是當(dāng)我們查看 a_tuple[0]時(shí)發(fā)現(xiàn)霍骄,列表已經(jīng)被改變了

>>> a_tuple[0]
['foo', 'item']

要明白為何會(huì)這樣,你需要知道:

  • (a) 如果一個(gè)對(duì)象實(shí)現(xiàn)了 iadd 魔術(shù)方法淡溯,它會(huì)在執(zhí)行 += 增強(qiáng)賦值時(shí)被調(diào)用读整,并且其返回值將用于該賦值語(yǔ)句;
  • (b) 對(duì)于列表來(lái)說(shuō)咱娶,iadd 等價(jià)于在列表上調(diào)用 extend 并返回該列表米间。

因此對(duì)于列表我們可以說(shuō) += 就是 list.extend 的“快捷方式”:

>>> a_list = []
>>> a_list += [1]
>>> a_list
[1]

>>> result = a_list.__iadd__([1])
>>> a_list = result

a_list 所引用的對(duì)象已被修改,而引用被修改對(duì)象的指針又重新被賦值給 a_list膘侮。
賦值的最終結(jié)果沒(méi)有變化屈糊,因?yàn)樗且?a_list 之前所引用的同一對(duì)象的指針,但仍然發(fā)生了賦值操作琼了。

因此逻锐,在我們的元組示例中,發(fā)生的事情等同于:

>>>
>>> result = a_tuple[0].__iadd__(['item'])
>>> a_tuple[0] = result
Traceback (most recent call last):
  ...
TypeError: 'tuple' object does not support item assignment

iadd 成功執(zhí)行雕薪,因此列表得到了擴(kuò)充昧诱,但是雖然 result 指向了 a_tuple[0] 已經(jīng)指向的同一對(duì)象,最后的賦值仍然導(dǎo)致了報(bào)錯(cuò)蹦哼,因?yàn)?code>元組是不可變的鳄哭。

序列的通用方法

所有的序列要糊,都支持以下的方法纲熏,而每個(gè)方法都支持我們?cè)谧远x序列類(lèi)型上實(shí)現(xiàn)這些操作。

in/not in

in 或 not in 是用來(lái)判斷元素是否存在于序列當(dāng)中锄俄。

>>> a = [1,2,3]
>>> 1 in a
True
>>> b = (1,2,3)
>>> 1 in b
True
>>> c = range(10)
>>> 1 in c
True

+

符號(hào) +是用來(lái)擴(kuò)展序列的局劲。而拼接不可變序列總是會(huì)生成新的對(duì)象。這意味著通過(guò)重復(fù)拼接來(lái)構(gòu)建序列的運(yùn)行時(shí)開(kāi)銷(xiāo)將會(huì)基于序列總長(zhǎng)度的乘方奶赠。如果想降低開(kāi)銷(xiāo)鱼填,只能采用一些其他的方法。

>>> a = [1,2,3]
>>> a1 = [4,5]
>>> a+a1
[1, 2, 3, 4, 5]

操作 +其實(shí)調(diào)用的是 __add__ 或者 __radd__毅戈。它們接收一個(gè)操作數(shù)苹丸,并根據(jù)是否是可變序列來(lái)返回一個(gè)新的對(duì)象或者更改自己的數(shù)據(jù)。

*

符號(hào)*+的多次自身拼接苇经。上面說(shuō)了 __add__是用來(lái)實(shí)現(xiàn)擴(kuò)展的赘理,那 *實(shí)際調(diào)用的就是 __mul__() 或者 __rmul__()

>>> a = [1,2,3]
>>> a*3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> 3*a
[1, 2, 3, 1, 2, 3, 1, 2, 3]

這里其實(shí)會(huì)有一個(gè)在創(chuàng)建多維列表時(shí)會(huì)出現(xiàn)的問(wèn)題扇单,當(dāng)你嘗試創(chuàng)建一個(gè)二維列表時(shí):[[1],[1],[1],[1]]

>>> a = [[1]] * 4
>>> a
[[1], [1], [1], [1]]
>>> a[0][0] = 2
>>> a
[[2], [2], [2], [2]]

我明明只給 a[0][0]賦值了商模,為什么整個(gè)列表中其他子列表的值都改變了呢?
這是因?yàn)槭褂?*創(chuàng)建列表時(shí),執(zhí)行重復(fù)操作并不是創(chuàng)建副本施流,而是創(chuàng)建對(duì)現(xiàn)有對(duì)象的引用响疚。
所以,當(dāng)我們創(chuàng)建多維列表時(shí)瞪醋,使用列表推導(dǎo)式會(huì)更好忿晕。

>>> a = [[1] for i in range(4)]
>>> a
[[1], [1], [1], [1]]
>>> a[0][0] = 2
>>> a
[[2], [1], [1], [1]]

取 [i]

序列都支持從位置 i 處獲取值,i 的范圍是 [0,len(list))趟章。

>>> a=[1,2,3]
>>> a[1]
2

[i] 操作調(diào)用的是 __getitem__(self, key)方法杏糙,接收的鍵應(yīng)為整數(shù)和切片對(duì)象。
而負(fù)數(shù)索引的特殊解讀是取決于這個(gè)方法的蚓土。

切片操作

通過(guò) range()的切片操作宏侍,可以很容易的看出它們的關(guān)系。

>>> a = range(10)
>>> a[1:4]
range(1, 4)
>>> a[2:5:3]
range(2, 5, 3)

len, min, max, count

這些函數(shù)都是支持序列操作的蜀漆。 len 既獲取序列數(shù)據(jù)的長(zhǎng)度谅河,min 既獲取最小值,max 既獲取最大值确丢,count 既用來(lái)獲取序列中某個(gè)數(shù)據(jù)的個(gè)數(shù)绷耍。

可變序列類(lèi)型的通用方法

l[i] = x

與取值 [i] 相對(duì)應(yīng)的,可變序列的 [i] 可以被修改賦值鲜侥。實(shí)際上調(diào)用的方法為 __setitem__褂始。

>>> a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a[0] = 2
>>> a
[2, 2, 3]

l[i:j] = x

與切片 [i:j] 相對(duì)應(yīng)的,切片替換也是一樣存在的描函。 l[i:j] = [i...j]崎苗。
注意:x 必須與它所替換的切片具有相同的長(zhǎng)度,既len(x) == j-i舀寓。

>>> a = [1,1,1,1,1,1]
>>> a
[1, 1, 1, 1, 1, 1]
>>> a[0:3] = [1,2,3]
>>> a
[1, 2, 3, 1, 1, 1]

del l[i:j]

等同于 l[i:j] = []

>>> a = [1,2,3]
>>> del a[0:1]
>>> a
[2, 3]

l.append(x)

將 x 添加到序列的末尾 (等同于 s[len(s):len(s)] = [x])

>>> a = []
>>> a.append(1)
>>> a
[1]

l.clear()

等同于 del l[:]

>>> a = [1,2,3,4]
>>> a.clear()
>>> a
[]

l.copy()

創(chuàng)建 s 的淺拷貝 (等同于 s[:]) ,淺拷貝指的是通過(guò) a 的值來(lái)構(gòu)建一個(gè)新的對(duì)象 b胆数,而 b 呢是跟 a 有著相同值得對(duì)象。

>>> a = [1,2,3]
>>> b = a.copy()
>>> b
[1, 2, 3]
>>> id(a)
4504616584
>>> id(b)
4504337160

s.extend(t) 或 s += t

用 t 的內(nèi)容擴(kuò)展 s (基本上等同于 s[len(s):len(s)] = t)

>>> a = [1]
>>> b = [2,3]
>>> a+=b
>>> a
[1, 2, 3]
>>> a.extend(b)
>>> a
[1, 2, 3, 2, 3]
>>>

s.insert(i, x)

在由 i 給出的索引位置將 x 插入 s (等同于 s[i:i] = [x])互墓。

>>> a = [1,2,3]
>>> b = [4,5]
>>> a.insert(0, b)
>>> a
[[4, 5], 1, 2, 3]
>>> a[0:0] = [b]
>>> a
[[4, 5], [4, 5], 1, 2, 3]

s.pop([i])

提取在 i 位置上的項(xiàng)必尼,并將其從 s 中移除,返回被移除的值。
注意:可選參數(shù) i 默認(rèn)為 -1篡撵,因此在默認(rèn)情況下會(huì)移除并返回最后一項(xiàng)判莉。

>>> a
[[4, 5], [4, 5], 1, 2, 3]
>>> a.pop(1)
[4, 5]
>>> c = a.pop(1)
>>> c
1

s.remove(x)

刪除 s 中第一個(gè) s[i] 等于 x 的項(xiàng)目。

>>> a = [1, 2, 1, 2]
>>> a.remove(1)
>>> a
[2, 1, 2]
>>> a.remove(2)
>>> a
[1, 2]

s.reverse()

就地將列表中的元素逆序育谬。當(dāng)反轉(zhuǎn)大尺寸序列時(shí) reverse() 方法會(huì)原地修改該序列以保證空間經(jīng)濟(jì)性券盅。 為提醒用戶(hù)此操作是通過(guò)間接影響進(jìn)行的,它并不會(huì)返回反轉(zhuǎn)后的序列斑司。

>>> a = [1,2,3,4]
>>> a
[1, 2, 3, 4]
>>> a.reverse()
>>> a
[4, 3, 2, 1]

后面的章節(jié)渗饮,將通過(guò)分析每個(gè)序列的使用與源碼但汞,進(jìn)行解讀。序列是 python 中非常重要的數(shù)據(jù)結(jié)構(gòu)互站,了解序列的構(gòu)成對(duì)深入學(xué)習(xí) python 有十分重要的作用私蕾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市胡桃,隨后出現(xiàn)的幾起案子踩叭,更是在濱河造成了極大的恐慌,老刑警劉巖翠胰,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件容贝,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡之景,警方通過(guò)查閱死者的電腦和手機(jī)斤富,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)锻狗,“玉大人满力,你說(shuō)我怎么就攤上這事∏峒停” “怎么了油额?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)刻帚。 經(jīng)常有香客問(wèn)我潦嘶,道長(zhǎng),這世上最難降的妖魔是什么崇众? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任掂僵,我火速辦了婚禮,結(jié)果婚禮上校摩,老公的妹妹穿的比我還像新娘看峻。我一直安慰自己阶淘,他們只是感情好衙吩,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著溪窒,像睡著了一般坤塞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上澈蚌,一...
    開(kāi)封第一講書(shū)人閱讀 52,255評(píng)論 1 308
  • 那天摹芙,我揣著相機(jī)與錄音,去河邊找鬼宛瞄。 笑死浮禾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盈电,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蝴簇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了匆帚?” 一聲冷哼從身側(cè)響起熬词,我...
    開(kāi)封第一講書(shū)人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吸重,沒(méi)想到半個(gè)月后互拾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嚎幸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年颜矿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嫉晶。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡或衡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出车遂,到底是詐尸還是另有隱情封断,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布舶担,位于F島的核電站坡疼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏衣陶。R本人自食惡果不足惜柄瑰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剪况。 院中可真熱鬧教沾,春花似錦、人聲如沸译断。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)孙咪。三九已至堪唐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翎蹈,已是汗流浹背淮菠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留荤堪,地道東北人合陵。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓枢赔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親拥知。 傳聞我的和親對(duì)象是個(gè)殘疾皇子糠爬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • http://python.jobbole.com/85231/ 關(guān)于專(zhuān)業(yè)技能寫(xiě)完項(xiàng)目接著寫(xiě)寫(xiě)一名3年工作經(jīng)驗(yàn)的J...
    燕京博士閱讀 7,582評(píng)論 1 118
  • 4.6. Sequence Types — list, tuple, range python擁有三種基本的序列類(lèi)...
    xpf2000閱讀 1,689評(píng)論 2 2
  • 寫(xiě)在前面的話(huà) 代碼中的# > 表示的是輸出結(jié)果 輸入 使用input()函數(shù) 用法 注意input函數(shù)輸出的均是字...
    FlyingLittlePG閱讀 2,771評(píng)論 0 8
  • 最近在慕課網(wǎng)學(xué)習(xí)廖雪峰老師的Python進(jìn)階課程,做筆記總結(jié)一下重點(diǎn)举庶。 基本變量及其類(lèi)型 變量 在Python中执隧,...
    victorsungo閱讀 1,701評(píng)論 0 5
  • 01 她和他高二文理分班的時(shí)候第一次見(jiàn)面。那時(shí)户侥,教室里的桌椅堆在一團(tuán)镀琉,他們到的比較早,動(dòng)手收拾蕊唐。他看到她那樣一個(gè)瘦...
    熙熙有曰閱讀 316評(píng)論 0 3