Python中大部分對象從邏輯上來說都是不可變的,因爲默認使用id作爲hash值,這表明在對象整個生命週期中hash保持不變,==操作也返回相同的結果,因此哪怕屬性改變了,從Python的角度來看這個對象也是不變的。
1. 列表以及元組的詳細簡介
跟字符串一樣,列表和元組也是序列型的數據類型,可以通過下標或者切片來訪問某一個或者某一連續的元素,列表更靈活的是列表和元組可以包含不同類型的對象。列表和元組在很多操作上是一樣的,最大的不同是:元組跟字符串一樣,是不可變的。這兩種數據類型如此相似,那爲何有了列表還需要元組呢?因爲在某些情況下,使用其中的一種類型要優於另一種。如:(1)你需要把一些敏感數據傳遞給一個並不瞭解的函數,你希望你的數據不被這個函數修改,此時當然選元組了。(2)你在處理動態數據時,需要經常更新這個數據結合,此時就應該選列表了。因此,這兩種數據類型各有各的用處,它們之間的轉換也十分的方便,通過內建函數list()把一個序列類型轉換成列表,通過tuple()把一個序列類型轉換成元組。
>>> s = u'alexzhou'
>>> list(s)
[u'a', u'l', u'e', u'x', u'z', u'h', u'o', u'u']
>>> tuple(s)
(u'a', u'l', u'e', u'x', u'z', u'h', u'o', u'u')
>>> s = ['alex','zhou']
>>> tuple(s)
('alex', 'zhou')
>>> s = ('alex','zhou')
>>> list(s)
['alex', 'zhou']
2. 列表常用操作
2.1 列表解析
>>> [i for i in range(8)]
[0, 1, 2, 3, 4, 5, 6, 7]
>>> [i+2 for i in range(8)]
[2, 3, 4, 5, 6, 7, 8, 9]
PS:range()函數返回一個列表
2.2 常用內建函數
(1)cmp()
列表之間的比較就是比較列表中的元素,遵循以下規則。
1.如果比較的元素是同類型的,則比較其值,返回結果.
2.如果兩個元素不是同一種類型,則檢查它們是否是數字.
a. 如果是數字,執行必要的數字強制類型轉換,然後比較.
b. 如果有一方的元素是數字,則另一方的元素”大”(數字是”最小的”)
c. 否則,通過類型名字的字母順序進行比較.
3.如果有一個列表首先到達末尾,則另一個長一點的列表”大”.
4.如果兩個列表的所有元素都是相等的,那麼返回0,表示兩列表大小相等.
>>> l1 = ['a','b']
>>> l2 = ['x','a']
>>> l3 = ['a','b']
>>> l4 = ['x','a','b']
>>> l5 = ['2','x']
>>> cmp(l1,l2)
-1
>>> cmp(l1,l3)
0
>>> cmp(l2,l4)
-1
>>> cmp(l1,l5)
1
(2)max()和min()
>>> s = ['alex','3','zhou']
>>> max(s)
'zhou'
>>> min(s)
'3'
(3)sorted()和reverse()
排序和逆序
>>> s = ['alex','3','zhou']
>>> s.reverse()
>>> s
['zhou', '3', 'alex']
>>> sorted(s)
['3', 'alex', 'zhou']
(4)enumerate()和zip()
enumerate函數可以同時打印index和value,zip函數接受任意多個序列作爲參數,將所有序列按相同的索引組合成一個元素是各個序列合併成的元組的新序列,新的序列的長度以參數中最短的序列爲準。
Python中,有3種內建的數據結構:列表、元組和字典。
list是處理一組有序項目的數據結構,即你可以在一個列表中存儲一個序列的項目。列表中的項目。列表中的項目應該包括在方括號中,這樣python就知道你是在指明一個列表。一旦你創建了一個列表,你就可以添加,刪除,或者是搜索列表中的項目。由於你可以增加或刪除項目,我們說列表是可變的數據類型,即這種類型是可以被改變的,並且列表是可以嵌套的。
實例:
#coding=utf-8
animalslist=['fox','tiger','rabbit','snake']
print "I don't like these",len(animalslist),'animals...'
for items in animalslist:
print items,
print "\\n操作後"
#對列表的操作,添加,刪除,排序
animalslist.append('pig')
del animalslist[0]
animalslist.sort()
for i in range(0,len(animalslist)):
print animalslist[i],
結果:
I don't like these 4 animals...
fox tiger rabbit snake
操作後
pig rabbit snake tiger
>>> sorted(s)
['3', 'alex', 'zhou']
>>> for i,obj in enumerate(s):
... print i,obj
...
0 alex
1 3
2 zhou
>>> s = ['alex','3','zhou']
>>> z = ['zhou','4','alex']
>>> zip(s,z)
[('alex', 'zhou'), ('3', '4'), ('zhou', 'alex')]
>>> for i,j in zip(s,z):
... print i,j
...
alex zhou
3 4
zhou alex
(5)reduce(function,sequence)和sum(sequence)
reduce函數把列表的前兩個元素作爲參數傳給function,返回計算的結果和列表的下一個元素重新作爲function的參數,直到列表的最後一個元素。
sum函數計算列表所有元素的總和,元素必須爲數字。
>>> s = ['a','b']
>>> sum(s)
Traceback (most recent call last):
File "", line 1, in
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> s = [1,2]
>>> sum(s)
3
>>> s = [1.5,2]
>>> sum(s)
3.5
>>>def add(x,y):
... return x+y
>>>reduce(add,range(10))
45
>>>sum(range(5),5)
15
(6)list()和tuple()
list函數和tuple函數把序列通過淺拷貝的方式創建一個列表或元組,常用於列表和元組間的相互轉換。
>>> l = [1,2,3]
>>> tuple(l)
(1, 2, 3)
>>> t = (1,2,3)
>>> list(t)
[1, 2, 3]
(7)列表內建函數
list.append(obj)
向列表中添加一個對象
>>> l = [1,2,3]
>>> l.append(4)
>>> l
[1, 2, 3, 4]
list.count(obj)
計算obj在列表中出現的次數
>>> l = [1,1,1,2,2]
>>> l.count(1)
3
list.extend(sequence)
把序列sequence的內容添加到列表
>>> l1 = [1,2]
>>> l2 = [3,4]
>>> l1.extend(l2)
>>> l1
[1, 2, 3, 4]
list.index(obj,i=0,j=len(list))
返回obj在列表中的索引值,如果不存在則拋出ValueError異常
>>> l = [1,2,3,4]
>>> l.index(1)
0
>>> l.index(5)
Traceback (most recent call last):
File "", line 1, in
ValueError: list.index(x): x not in list
list.insert(index,obj)
在列表的指定索引處插入對象obj,如果index大於列表的長度,則插入到列表最後
>>> l = [1,2,3,4]
>>> l.insert(1,'a')
>>> l
[1, 'a', 2, 3, 4]
>>> l.insert(9,'a')
>>> l
[1, 'a', 2, 3, 4, 'a', 'a']
list.pop(index=-1)
刪除並返回列表中指定位置的對象,默認是最後一個元素,若index超出列表長度,則拋出IndexError異常
>>> l = [1,2,3,4]
>>> l.pop()
4
>>> l
[1, 2, 3]
>>> l.pop(0)
1
>>> l
[2, 3]
>>>l.pop(9)
Traceback (most recent call last):
File "", line 1, in
IndexError: pop index out of range
list.remove(obj)
從列表中刪除對象,若對象不存在則拋出ValueError異常
>>> l = [1,2,3]
>>> l.remove(1)
>>> l
[2, 3]
>>> l.remove('a')
Traceback (most recent call last):
File "", line 1, in
ValueError: list.remove(x): x not in list
3. 元組常用操作
3.1 元組元素的可變性
元組跟列表的操作很相近,具體操作可以參考以上列表操作,不過由於元組的不可變特效,可以將元組作爲字典的key。要注意的是:元組的不可變特效只是對於元組本身而言,如果元組內的元素是可變的對象,是可以改變其值的。
>>> t = ([1,2],3,4)
>>> t[0][0] = 3
>>> t
([3, 2], 3, 4)
>>> t[1] = 5
Traceback (most recent call last):
File "", line 1, in
TypeError: 'tuple' object does not support item assignment
3.2 單元素元組
由於圓括號被重載,單元素元組需要在後面添加一個逗號。
>>> t = (1)
>>> type(t)
>>> t = (1,)
>>> type(t)
4. python對象淺拷貝和深拷貝
淺拷貝是新建一個跟原來類型一樣的對象(身份是新的:id(obj)),不過其內容是原來對象元素的引用(內容是舊的),是序列類型對象默認的拷貝方式,
深拷貝則包括對象及其內容都是新的,下面的這些操作是淺拷貝。
(1)完全切片操作[:]
(2)利用工廠函數,比如 list(),dict()等
(3)使用 copy 模塊的 copy 函數
下面通過一個例子來說明淺拷貝和深拷貝
4.1 創建一個列表,並採用上面三種方式進行淺拷貝
>>> user = ['user_id',['username','alexzhou']]
>>> alex = user[:]
>>> zhou = list(user)
>>> import copy
>>> hai = copy.copy(user)
>>> [id(x) for x in user,alex,zhou,hai]
[140325195435976, 140325195478368, 140325195480528, 140325195480600]
從上面可以看出,各個對象的id是不一樣的
4.2 嘗試改變各列表的值,看看會發生什麼事
>>> alex[0] = '1'
>>> zhou[0] = '2'
>>> hai[0] = '3'
>>> user,alex,zhou,hai
(['user_id', ['username', 'alexzhou']], ['1', ['username', 'alexzhou']], ['2', ['username', 'alexzhou']], ['3', ['username', 'alexzhou']])
>>> alex[1][1] = 'test'
>>> user,alex,zhou,hai
(['user_id', ['username', 'test']], ['1', ['username', 'test']], ['2', ['username', 'test']], ['3', ['username', 'test']])
>>> [id(x) for x in alex]
[140325295415488, 140325195435400]
>>> [id(x) for x in zhou]
[140325295406992, 140325195435400]
>>> [id(x) for x in hai]
[140325195481664, 140325195435400]
從測試結果可以看出,非容器類型(數字、字符串等)沒有發生拷貝操作,各列表中的user_id互不影響,id也不一樣;改變了alex中列表的值,其它對象中列表的值也受到了影響,並且id的值是一樣的,表明各對象中列表的內容都是指向同一對象的,所以發生了淺拷貝操作。
4.3 進行深拷貝操作
>>> jiang = copy.deepcopy(user)
>>> jiang
['user_id', ['username', 'test']]
>>> [id(x) for x in jiang]
[140325195467488, 140325195480456]
>>> alex[1][1] = 'alex'
>>> alex,zhou,hai,jiang
(['1', ['username', 'alex']], ['2', ['username', 'alex']], ['3', ['username', 'alex']], ['user_id', ['username', 'test']])
可以看到對象jiang的id跟其它淺拷貝對象是不一樣的,改變對象alex列表中元素的值對jiang對象沒有任何影響。注意:如果對象是不可變類型,如元組或者數字、字符串等,那麼對它進行深拷貝也只能得到淺拷貝對象。
>>> user1 = ['user_id',('username','alex')]
>>> user2 = copy.deepcopy(user1)
>>> [id(x) for x in user1,user2]
[140325195477936, 140325195480168]
>>> [id(x) for x in user1]
[140325195467488, 140325195435112]
>>> [id(x) for x in user2]
[140325195467488, 140325195435112]
總結:今天跟大家分享的如何分辨python語言中列表、元組的區別到這裏就結束了。