目錄關鍵字unsigned和signed數據在電腦中的存儲原碼 與 補碼的轉化與硬體關係原,反,補的原理:整型存儲的本質變數存取的過程類型目前的作用十進位與二進位快速轉換大小端位元組序判斷當前機器的位元組序"負零"(-128)的理解截斷建議在無符號類型的數值後帶上u, 關鍵字unsigned和sign ...
列表
Python的列表是:
-
任意對象的有序集合
-
通過偏移訪問
-
可變長度、異構以及任意嵌套
-
屬於“可變序列”的分類
-
對象引用數組
下表是常見/具有代表性的列表對象操作:
操作 | 解釋 |
---|---|
L = [] |
一個空的列表 |
L = [123, 'abc', 1.23, {}] |
有四個項的列表,索引從0到3 |
L = list('spam') |
一個可迭代對象元素的列表 |
L = list(range(-4, 4)) |
連續整數的列表 |
L[i] |
索引 |
L[i][j] |
索引的索引(用於列表嵌套列表) |
L[i:j] |
分片 |
len(L) |
求長度 |
L1 + L2 |
拼接 |
L * 3 |
重覆 |
for x in L: print(x) |
迭代 |
3 in L |
成員關係 |
L.append(4) |
尾部添加 |
L.extend([5, 6, 7]) |
尾部擴展 |
L.insert(i, X) |
插入 |
L.index(X) |
索引 |
L.count(X) |
統計元素出現個數 |
L.sort() |
排序 |
L.reverse() |
反轉 |
L.copy() |
複製 |
L.clear() |
清除 |
L.pop(i) |
刪除i 處元素,並將其返回 |
L.remove(X) |
刪除元素X |
del L[i] |
刪除i 處元素 |
del L[i:j] |
刪除i 到j 處的片段 |
L[i:j] = [] |
刪除i 到j 處的片段 |
L[i] = 3 |
索引賦值 |
L[i:j] = [4, 5, 6] |
分片賦值 |
L = [x ** 2 for x in range(5)] |
列表推導和映射 |
list(map(ord, 'spam')) |
構造列表 |
列表的字面量表達式是一系列對象,括在方括弧里並用逗號隔開。上面的表中的一些操作與字元串類似。
列表的實際應用
基本列表操作:
len
求長度、+
拼接、*
重覆:
>>> len([1, 2, 3])
3
>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> ['Ni!'] * 4
['Ni!', 'Ni!', 'Ni!', 'Ni!']
這裡要求+
的兩邊必須是列表,否則會出現類型錯誤。
列表迭代與推導
列表對所有序列操作都能做出相應,包括for
:
>>> 3 in [1, 2, 3] # 3是否是列表的成員
True
>>> for x in [1, 2, 3]: # 迭代
... print(x, end=' ')
...
1 2 3
for
會從左到右地遍歷任何序列中的項,對每一項執行每一條子句(在for語句後輸入提示符為...
的若幹行)。
列表推導:通過對序列中的每一項應用一個表達式來構建新的列表的方式,用到for
:
>>> res = [c * 4 for c in 'SPAM']
>>> res
['SSSS', 'PPPP', 'AAAA', 'MMMM']
相較於使用for
語句構造列表,列表推導更簡單。map
也能實現類似效果,它對序列中的每一項應用一個函數,並把結果收集到一個新的列表中:
>>> list(map(abs, [-1, -2, 0, 1, 2]))
[1, 2, 0, 1, 2]
索引、分片和矩陣
索引和分片的操作與字元串相同。但是,列表索引的結果是指定偏移處的對象,而分片返回新列表:
>>> L = ['spam', 123, [1, 2, 3]]
>>> L[2]
[1, 2, 3]
>>> L[-2]
123
>>> a = L[2]
>>> L[2][1] = 4
>>> a
[1, 4, 3]
由於列表可以嵌套列表,我們有時候需要將幾次索引操作連在一起,以矩陣為例:
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> matrix[1]
[4, 5, 6]
>>> matrix[1][1]
5
原位置修改列表
列表是可變的,支持原地修改。
索引與分片的賦值
可以將一個對象賦值給一個特定項(偏移)或整個片段(分片)來改變它的內容:
>>> L = ['spam', 'Spam', 'SPAM!']
>>> L[1] = 'eggs'
>>> L
['spam', 'eggs', 'SPAM!']
>>> L[0:2] = ['eat', 'more']
>>> L
['eat', 'more', 'SPAM!']
分片賦值可以分成兩步理解。插入:刪除等號左邊指定的分片;插入:將包含在等號右邊的可迭代對象中的片段插入舊分片被刪除的位置。這意味著,等號左邊分片的長度不一定要等於右邊列表的長度。
這樣,分片賦值可以寫成插入或刪除操作。
>>> L = [1, 2, 3]
>>> L[1:2] = [4, 5] # 替換
>>> L
[1, 4, 5, 3]
>>> L[1:1] = [6, 7] # 插入
>>> L
[1, 6, 7, 4, 5, 3]
>>> L[1:2] = [] # 刪除
>>> L
[1, 7, 4, 5, 3]
也可以用於在列表頭部拼接:
>>> L = [1]
>>> L[:0] = [2, 3, 4]
>>> L
[2, 3, 4, 1]
>>> L[len(L):] = [5, 6, 7]
>>> L
分片替換是強大的功能,但我們更經常用replace
、insert
等。
列表方法調用
Python列表支持特定類型方法調用,這些方法可以原地修改列表。其中append
方法在列表末尾添加單一對象(不生成新的列表),sort
方法給列表中的內容排序。
>>> L = ['eat', 'more', 'SPAM!']
>>> L.append('please')
>>> L
['eat', 'more', 'SPAM!', 'please']
>>> L.sort()
>>> L
['SPAM!', 'eat', 'more', 'please']
更多關於列表排序
在預設情況下,sort
使用Python的預設比較(這裡是字元串比較),以及升序排序。可以通過關鍵詞參數修改sort
。關鍵詞參數是函數調用中的一種特殊的name=value
語法,通過名字傳遞。
在sort
中,reverse
指定排序是升序的,還是降序的;key
參數返回在排序中使用的值,讓sort
根據key(元素)
的值給元素排序。
>>> L = ['abc', 'ABD', 'aBe']
>>> L.sort()
>>> L
['ABD', 'aBe', 'abc']
>>> L.sort(key=str.lower)
>>> L
['abc', 'ABD', 'aBe']
>>> L.sort(key=str.lower, reverse=True)
>>> L
['aBe', 'ABD', 'abc']
註意,append
和sort
修改原位置的列表對象,但不返回列表。如果我們要得到一個新的、重新排序的列表,並且要返回這個列表,那麼要用sorted()
,他不會原地修改列表。
>>> L = ['abc', 'ABD', 'aBe']
>>> sorted(L, key=str.lower, reverse=True)
['aBe', 'ABD', 'abc']
其他常見的列表方法
reverse
原地反轉列表,extend
在末端插入多個元素,pop
在末端刪除一個元素並返回這個元素。當然,也有reversed
函數返回新的對象。
>>> L = [1, 2]
>>> L.extend([3, 4, 5])
>>> L
[1, 2, 3, 4, 5]
>>> L.pop()
5
>>> L
[1, 2, 3, 4]
>>> L.reverse()
>>> L
[4, 3, 2, 1]
>>> list(reversed(L))
[1, 2, 3, 4]
append
也可以在尾部添加元素,但只能添加一個:
>>> L = []
>>> L.append(1)
>>> L.append(2)
>>> L
[1, 2]
pop
可以接受偏移量,指定要刪除的元素。remove
通過值刪除元素,insert
在特定位置插入元素,count
計算某元素的出現次數,index
查找某元素第一次出現在列表中的位置。
>>> L = ['spam', 'eggs', 'ham']
>>> L.index('eggs')
1
>>> L.insert(1, 'toast')
>>> L
['spam', 'toast', 'eggs', 'ham']
>>> L.remove('eggs')
>>> L
['spam', 'toast', 'ham']
>>> L.pop(1)
'toast'
>>> L.count('spam')
1
其他常見列表操作
del
可以刪除索引或分片:
>>> L = ['spam', 'eggs', 'ham', 'toast']
>>> del L[0]
>>> L
['eggs', 'ham', 'toast']
>>> del L[1:]
>>> L
['eggs']
這可以通過將一個分片L[i:j]
賦值為空列表來實現。
L.copy()
方法、L[:]
和list(L)
都能實現列表的頂層複製。
字典
Python中的字典的主要屬性:
-
通過鍵而不是偏移量來讀取
-
任意對象的無序集合
-
長度可變、異構、任意嵌套
-
屬於“可變映射”類型(不支持序列操作)
-
對象引用表(散列表)
常見/具有代表性的字典操作:
操作 | 解釋 |
---|---|
D = {} |
空字典 |
D = {'name': 'Bob', 'age': 40} |
有兩個元素的字典 |
E = {'cto': {'name': 'Bob', 'age': 40}} |
嵌套 |
D = dict(name='Bob', age=40) |
通過關鍵字參數構造字典 |
D = dict([('name', 'Bob'), ('age', 40)]) |
通過鍵值對構造字典 |
D = dict(zip(keylist, valslist)) |
通過拉鏈式鍵值對構造字典 |
D = dict.fromkeys(['a', 'b']) |
鍵列表 |
D['name'] |
通過鍵索引 |
E['eto']['age'] |
嵌套索引 |
'age' in D |
成員關係:是否存在鍵 |
D.keys() |
所有鍵 |
D.values() |
所有值 |
D.items() |
所有“鍵+值”元組 |
D.copy() |
複製 |
D.clear() |
刪除所有內容 |
D.update(D2) |
通過鍵合併 |
D.get(key, default?) |
通過鍵獲取,如果不存在預設返回None |
D.pop(key, default?) |
通過鍵刪除,如果不存在返回錯誤 |
D.setdefault(key, default?) |
通過鍵獲取,如果不存在預設設置為None |
D.popitem() |
刪除/返回所有的鍵值 |
len(D) |
長度(鍵值對的對數) |
D[key] = 42 |
新增/修改鍵 |
del D [key] |
根據鍵刪除條目 |
list(D.keys()) |
查看字典鍵 |
D1.keys() & D2.keys() |
|
Dictionary views |
查看字典鍵 |
D = {x: x * 2 for x in range(10)} |
字典推導 |
字典的實際應用
字典的基本操作
通常情況下,創建字典並通過鍵來存儲、訪問其中的某項:
>>> D = {'spam': 2, 'ham': 1, 'eggs': 3}
>>> D['spam']
2
>>> D
{'spam': 2, 'ham': 1, 'eggs': 3}
這裡的字典是D
,鍵'spam'
的值為2,我們用方括弧語法,用鍵對字典進行索引操作。
內置的len
也適用於字典,返回存儲在字典中的元素的數目(鍵的數目);字典的in
成員關係運算符檢查鍵是否在字典中;keys
方法返回列表中所有的鍵。
>>> len(D)
3
>>> 'ham' in D
True
>>> list(D.keys())
['spam', 'ham', 'eggs']
註意,keys
方法不返回列表,而是返回dict_keys
類型,因此需要list
轉換成列表。
原位置修改字典
字典也是可變的,因此可以在原位置對其修改、增大以及縮短。只需要給一個鍵賦值就可以改變或者生成元素。del
也適用於字典,用於刪除作為索引的鍵相關聯的元素。字典支持所有類型,包括嵌套列表。
>>> D
{'spam': 2, 'ham': 1, 'eggs': 3}
>>> D['ham'] = ['grill', 'bake', 'fry'] # 改變索引對應的值
>>> D
{'spam': 2, 'ham': ['grill', 'bake', 'fry'], 'eggs': 3}
>>> del D['eggs'] # 刪除元素
>>> D
{'spam': 2, 'ham': ['grill', 'bake', 'fry']}
>>> D['brunch'] = 'Bacon' # 生成元素(原來的字典沒有`'brunch'`鍵)
>>> D
{'spam': 2, 'ham': ['grill', 'bake', 'fry'], 'brunch': 'Bacon'}
其他字典方法
字典的values
、items
方法分別返回字典的所有值列表和(key, value)
對元組。這兩個方法返回可迭代對象,可以將其轉換為列表。
>>> D = {'spam': 2, 'ham': 1, 'eggs': 3}
>>> list(D.values())
[2, 1, 3]
>>> list(D.items())
[('spam', 2), ('ham', 1), ('eggs', 3)]
讀取不存在的鍵會出錯,但是通過get
方法讀取不存在的鍵會返回None
或自定義的值。這對於不知道鍵是否存在的時候非常有用。
>>> D['spam']
2
>>> D.get('spam')
2
>>> D['toast']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'toast'
>>> D.get('toast')
>>> D.get('toast')
>>> print(D.get('toast'))
None
>>> print(D.get('toast', 0))
0
update
方法類似於拼接,把一個字典的鍵和值拼接到另一個字典中。
>>> D
{'spam': 2, 'ham': 1, 'eggs': 3}
>>> D2 = {'spam': 3, 'toast': 4, 'muffin': 5}
>>> D.update(D2)
>>> D
{'spam': 3, 'ham': 1, 'eggs': 3, 'toast': 4, 'muffin': 5}
pop
方法刪除一個鍵並返回值。
>>> D
{'spam': 3, 'ham': 1, 'eggs': 3, 'toast': 4, 'muffin': 5}
>>> D.pop('muffin')
5
>>> D.pop('toast')
4
>>> D
{'spam': 3, 'ham': 1, 'eggs': 3}
字典用法註意事項
- 序列運算無效:字典的元素沒有“順序”的概念,因此拼接、分片無效;
- 對新索引賦值會添加項
- 鍵不一定總是字元串
用字典模擬靈活的列表:整數鍵
用較大的數作為偏移值修改列表中的值會報錯,但這種情況不會再字典中出現。
>>> L = []
>>> L[99] = 'spam'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> D = {}
>>> D[99] = 'spam'
>>> D
{99: 'spam'}
用整數作為鍵,我們可以把字典看作更具有靈活性的表。
對稀疏數據結構使用字典:用元組作鍵
字典鍵也常用於實現稀疏數據結構。
>>> Matrix = {}
>>> Matrix[(2, 3, 4)] = 88
>>> Matrix[(7, 8, 9)] = 99
>>> X = 2
>>> Y = 3
>>> Z = 4
>>> Matrix[(X, Y, Z)]
88
>>> Matrix
{(2, 3, 4): 88, (7, 8, 9): 99}
這種方法可以只存儲兩個有值的點,而不是整個三維數組;缺點是不能訪問非存儲點的坐標。
避免鍵不存在錯誤
可以用if
和try
方法檢測值是否存在(這兩個方法在第10章學習)。
>>> if (2, 3, 6) in Matrix:
... print(Matrix[(2, 3, 6)])
... else:
... print(0)
...
0
>>> try:
... print(Matrix[(2, 3, 6)])
... except KeyError:
... print(0)
...
0
但是最簡潔的辦法是get
。
>>> Matrix.get((2, 3, 4), 0)
88
>>> Matrix.get((2, 3, 6), 0)
0
字典的嵌套
一般來說,字典可以取代搜索數據結構,並可以表示多種結構化信息。
Python的內置數據類型可以很輕鬆地表達結構化信息,下麵代碼可以一次性地寫好字典,而不是分開對每個鍵賦值:
>>> rec = {'name': 'Bob',
... 'jobs': ['developer', 'manager'],
... 'web': 'www.bobs.com/?Bob',
... 'home': {'state': 'Overworked', 'zip': 12345}}
訪問嵌套對象地元素時,只要簡單地把連續地索引操作用起來:
>>> rec['jobs'][1]
'manager'
>>> rec['home']['zip']
12345
創建字典地其他方式
創建字典有四種方式:
>>> # 第一種
>>> {'name': 'Bob', 'age': 40}
>>> # 第二種
>>> D = {}
>>> D['name'] = 'Bob'
>>> D['age'] = 40
>>> # 第三種
>>> dict(name='Bob', age=40)
>>> # 第四種
>>> dict([('name', 'Bob'), ('age', 40)])
適用條件:
- 事先可以拼出整個字典:第一種;
- 需要一次動態地建立字典地一個欄位:第二種;
- 鍵是字元串:第三種;
- 通過序列構建字典:第四種。
最後一種形式會與zip
一起用,把程式運行時動態獲取的單獨鍵列表和單獨值列表一一對應拼接在一起:
dict(zip(keyslist, valueslist))
如果要所有鍵對應的值相同,我們可以用fromkeys
方法初始化,傳入一個鍵的列表和一個初始值:
>>> dict.fromkeys(['a', 'b', 'c'], 0)
{'a': 0, 'b': 0, 'c': 0}
請留意:字典vs列表
列表將元素賦值給位置,而字典將元素賦值給更加便於記憶的鍵。在實際生活中,字典適用於存儲帶有標簽的數據,或者是通過名稱直接快速查詢的結構。
Python 3.X和2.7中的字典變化
Python 3.X中的列表:
- 支持新的字典推導表達式
- 對於
D.keys
、D.values
和D.items
方法,不是返回列表,而是其他可迭代對象 - 不再直接支持相對大小的比較,而是手動比較
- 沒有
has_key
,改為in
成員關係測試
3.X和2.7的字典推導
我們可以用zip
內置函數從值和鍵的列表中構造字典。
>>> D = dict(zip(['a', 'b', 'c'], [1, 2, 3]))
>>> D
{'a': 1, 'b': 2, 'c': 3}
在3.X和2.7中,我們可以用一個字典推導表達式來代替:
>>> D = {k: v for (k, v) in zip(['a', 'b', 'c'], [1, 2, 3])}
>>> D
{'a': 1, 'b': 2, 'c': 3}
我們可以使用推導把單獨的一串值映射到字典,可以用表達式計算:
>>> D = {x: x ** 2 for x in [1, 2, 3, 4]}
>>> D
{1: 1, 2: 4, 3: 9, 4: 16}
>>>
>>> D = {c: c * 4 for c in 'SPAM'}
>>> D
{'S': 'SSSS', 'P': 'PPPP', 'A': 'AAAA', 'M': 'MMMM'}
我們可以用這種字典推導,將所有鍵初始化到同一個值。
3.X中的字典視圖
在3.X中,字典的keys
、values
和items
返回視圖對象,在2.X中返回列表。視圖對象是可迭代對象,但不是列表。
運行這三個方法的結果:
>>> D = dict(a=1, b=2, c=3)
>>> D
{'a': 1, 'b': 2, 'c': 3}
>>> D.keys()
dict_keys(['a', 'b', 'c'])
>>> list(D.keys())
['a', 'b', 'c']
>>> D.values()
dict_values([1, 2, 3])
>>> list(D.values())
[1, 2, 3]
>>> D.items()
dict_items([('a', 1), ('b', 2), ('c', 3)])
>>> list(D.items())
[('a', 1), ('b', 2), ('c', 3)]
Python 3.X的字典自己就有迭代器,它返回連續鍵。
>>> for key in D: print(key)
...
a
b
c
Python 3.X的字典視圖可以動態地反映視圖對象創建之後對字典做出的修改:
>>> K = D.keys()
>>> V = D.values()
>>> K, V
(dict_keys(['a', 'b', 'c']), dict_values([1, 2, 3]))
>>> del D['b']
>>> D
{'a': 1, 'c': 3}
>>> K
dict_keys(['a', 'c'])
>>> V
dict_values([1, 3])
字典視圖和集合
字典的keys
可以視為集合,但values
不能。
>>> K, V
(dict_keys(['a', 'c']), dict_values([1, 3]))
>>> K | {'x': 4}
{'c', 'x', 'a'}
>>> V & {'x': 4}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'dict_values' and 'dict'
>>> V & {'x': 4}.values()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'dict_values' and 'dict_values'
在集合操作中,視圖可能和其他視圖、集合和字典混合。
>>> D = {'a': 1, 'b': 2, 'c': 3}
>>> D.keys() & D.keys() # 視圖與視圖
{'b', 'c', 'a'}
>>> D.keys() & {'b'} # 視圖與集合
{'b'}
>>> D.keys() & {'b': 1} # 視圖與字典
{'b'}
如果字典項視圖是可散列的,那麼它們可以被視為集合。
3.X中的字典鍵排序
我們不能直接對視圖對象進行排序,需要將其轉換為列表,或者對其進行sorted()
函數,返回一個新的列表。
3.X中字典大小比較不再有效
在python 3.X中不能直接用<
、>
比較字典相對大小,但可以用==
。
在 3.X中has_key方法已死:in方法萬歲
has_key
方法已經在3.X取消,用in
成員關係表達式代替。
>>> D
{'a': 1, 'b': 2, 'c': 3}
>>> D.has_key('c')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict' object has no attribute 'has_key'
>>> 'c' in D
True