一文搞懂Python中的所有陣列資料型別
關於我
一個有思想的程式猿,終身學習實踐者,目前在一個創業團隊任team lead,技術棧涉及Android、Python、Java和Go,這個也是我們團隊的主要技術棧。
Github:https://github.com/hylinux1024
微信公眾號:終身開發者(angrycode)
陣列型別是各種程式語言中基本的陣列結構了,本文來盤點下Python
中各種“陣列”型別的實現。
list
tuple
array.array
str
bytes
bytearray
其實把以上型別都說成是陣列是不準確的。這裡把陣列當作一個廣義的概念,即把列表、序列、陣列都當作array-like
資料型別來理解。
**注意本文所有程式碼都是在Python3.7
中跑的^_^**
0x00 可變的動態列表list
list
應該是Python
最常用到的陣列型別了。它的特點是可變的、能動態擴容,可儲存Python
中的一切物件,使用時不用指定儲存的元素的型別。
使用非常簡單
>>> arr = ["one","two","three"] >>> arr[0] 'one' # 動態擴容 >>> arr.append(4) >>> arr ['one', 'two', 'three', 4] # 刪除一個元素 >>> del arr[2] >>> arr ['one', 'two', 4]
0x01 不可變的tuple
tuple
的操作與list
類似。它的特點是不可變,不能擴容,可儲存Python
中的一切物件,使用時不用指定儲存的元素的型別。
>>> t = 'one','two',3 >>> t ('one', 'two', 3) >>> t.append(4) AttributeError: 'tuple' object has no attribute 'append' >>> del t[0] TypeError: 'tuple' object doesn't support item deletion
tuple
可以使用+
運算子,這個運算將建立一個新的tuple
物件用於儲存資料。
>>> t+(1,)
('one', 'two', 3, 1)
>>> tcopy = t+(1,)
>>> tcopy
('one', 'two', 3, 1)
>>> id(tcopy)
4604415336
>>> id(t)
4605245696
可以看出tuple
執行+
運算子之後兩個物件的地址是不一樣
0x02 array.array
如果在Python
中要用到其它語言中類似“陣列”的資料結構,就需要用到array
模組了。它的特點是可變的、儲存相同型別的數值,不能儲存物件。
因為array
在使用的時候要指定元素資料型別,因此它比list
和tuple
都有比較高效空間效能。
# 使用時指定元素資料型別為`float`
>>> arr = array.array('f', (1.0, 1.5, 2.0, 2.5))
>>> arr
array('f', [1.0, 1.5, 2.0, 2.5])
# 修改一個元素
>>> arr[1]=12.45
>>> arr
array('f', [1.0, 12.449999809265137, 2.0, 2.5])
# 刪除一個元素
>>> del arr[2]
>>> arr
array('f', [1.0, 12.449999809265137, 2.5])
# 增加一個元素
>>> arr.append(4.89)
>>> arr
array('f', [1.0, 12.449999809265137, 2.5, 4.889999866485596])
# 如果將一個字串型別資料儲存到一個浮點數的陣列將會報錯
>>> arr[0]='hello'
TypeError: must be real number, not str
array
中元素的資料型別可以參考下表
Type code | C Type | Python Type |
---|---|---|
'b' | signed char | int |
'B' | unsigned char | int |
'u' | Py_UNICODE | Unicode character |
'h' | signed short | int |
'H' | unsigned short | int |
'i' | signed int | int |
'I' | unsigned int | int |
'l' | signed long | int |
'L' | unsigned long | int |
'q' | signed long long | int |
'Q' | unsigned long long | int |
'f' | float | float |
'd' | double | float |
0x03 字串序列str
Python3
中使用str
物件來表示一個文字字元序列(看,這跟Java
中的字串String
是多麼相似呢)。它的特點不可變的Unicode
字元序列。
在str
中它的每一個元素都是字串物件。
>>> s ='123abc'
>>> s
'123abc'
>>> s[0]
'1'
>>> s[2]
'3'
# 字串是不可變的序列,不能刪除其中的元素
>>> del s[1]
TypeError: 'str' object doesn't support item deletion
# 要對字串進行操作,可以轉化成list
>>> sn = list(s)
>>> sn
['1', '2', '3', 'a', 'b', 'c']
>>> sn.append(9)
>>> sn
['1', '2', '3', 'a', 'b', 'c', 9]
# 字串中的元素也是字串物件
>>> type(s[2])
<class 'str'>
>>> type(s)
<class 'str'>
str
物件也可以執行+
操作,它也會生成一個新物件用於儲存。
>>> s2 = s+'33'
>>> s2
'123abc33'
>>> id(s2)
4605193648
>>> id(s)
4552640416
0x04 bytes
bytes
物件用於儲存位元組序列,它的特點是不可變儲存,可儲存0-256的數值。
>>> b = bytes([0,2,4,8])
>>> b[2]
4
>>> b
b'\x00\x02\x04\x08'
>>> b[0]=33
TypeError: 'bytes' object does not support item assignment
>>> del b[0]
TypeError: 'bytes' object doesn't support item deletion
0x05 bytearray
bytearray
物件與bytes
類似,用於儲存位元組序列。它的特點是可變的,能動態擴容的位元組陣列。
>>> ba = bytearray((1,3,5,7,9))
>>> ba
bytearray(b'\x01\x03\x05\x07\t')
>>> ba[1]
3
# 刪除一個元素
>>> del ba[1]
>>> ba
bytearray(b'\x01\x05\x07\t')
>>> ba[0]=2
>>> ba[0]
2
# 新增一個元素
>>> ba.append(6)
# 只能新增位元組
>>> ba.append(s)
TypeError: 'str' object cannot be interpreted as an integer
>>> ba
bytearray(b'\x02\x05\x07\t\x06')
# 位元組的範圍是0-256
>>> ba[2]=288
ValueError: byte must be in range(0, 256)
bytearray
可以轉化成bytes
物件,但效率不是很高。
# bytearray轉成bytes將生成一個新物件
>>> bn = bytes(ba)
>>> id(bn)
4604114344
>>> id(ba)
4552473544
0x06 各個型別相互轉化
tuple->list
>>> tuple(l)
('a', 'b', 'c')
list->tuple
>>> t
('a', 'b', 'c')
>>> list(t)
['a', 'b', 'c']
str->list
>>> l = list('abc')
>>> l
['a', 'b', 'c']
list->str
>>> l
['a', 'b', 'c']
>>> ''.join(l)
'abc'
str->bytes
>>> s = '123'
>>> bytes(s)
TypeError: string argument without an encoding
>>> bytes(s,encoding='utf-8')
b'123'
# 或者使用str的encode()方法
>>> s.encode()
b'123'
bytes->str
>>> b = b'124'
>>> b
b'124'
>>> type(b)
<class 'bytes'>
>>> str(b,encoding='utf-8')
'124'
# 或使用bytes的decode()
>>> b.decode()
'124'
0x07 總結
這些資料型別都是Python
自帶的,在實際開發中應該根據具體需求選擇合適的資料型別。例如當要儲存的元素型別是多種多樣的,那麼就應該使用list
或者tuple
。而array.array
相對來說擁有較好的空間效能,但它只能儲存單一型別。
我相信在很多業務場景中list
或tuple
是可以滿足需求的,只是其它資料結構也要有所瞭解,在我們做一些基礎元件時,會考慮資料結構的效能,或者閱讀他人的程式碼時,能做到心中有數。
0x08 學習資料
- https://docs.python.org/3.1/library/functions.html#bytearray
- https://docs.python.org/zh-cn/3/library/array.html
- https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str