4種非常實(shí)用的python內(nèi)置數(shù)據(jù)結(jié)構(gòu)
array
Python不僅僅可以使用內(nèi)置的list實(shí)現(xiàn)數(shù)組,還支持像C語言那樣的指定類型的原生數(shù)組array。
很顯然,因?yàn)閘ist可以存儲(chǔ)各種類型的對(duì)象,而array只存儲(chǔ)一個(gè)指定的原生類型,所以當(dāng)數(shù)據(jù)量較大時(shí),原生array在內(nèi)存占用方面要比list小。
而且array不像C語言里那樣在定義時(shí)就限制了大小,它支持list所支持的各種常用函數(shù)。相比之下Python的array更像是C++的vector。
from array import array l = list(range(100)) a = array.fromlist(l) print(l.__sizeof__(), a.__sizeof__())
目前array有兩個(gè)限制。首先,它只支持整數(shù)、小數(shù)、unicode字符,而不能像C++的vector那樣支持多種數(shù)據(jù)類型。另外目前指定類型比較麻煩,我們需要使用類型對(duì)應(yīng)的字母縮寫來指定,而不能使用簡單的諸如int,float的方式。
a = array('i')
a.append(1)
a.append(4)
| Type code | C Type | Python Type | Minimum size in bytes |
| 'b' | signed char | int | 1 |
| 'B' | unsigned char | int | 1 |
| 'u' | wchar_t | Unicode character | 2 |
| 'h' | signed short | int | 2 |
| 'H' | unsigned short | int | 2 |
| 'i' | signed int | int | 2 |
| 'I' | unsigned int | int | 2 |
| 'l' | signed long | int | 4 |
| 'L' | unsigned long | int | 4 |
更詳細(xì)的信息可以參考:https://docs.python.org/3.8/library/array.html
defaultdict
C++的map對(duì)于新的key會(huì)自動(dòng)使用value type的默認(rèn)構(gòu)造函數(shù)構(gòu)造一個(gè)值,而Python默認(rèn)的dict對(duì)于不存在的key的訪問會(huì)拋出異常(賦值除外)。這是因?yàn)镻ython不知道value的類型,所以沒辦法為我們默認(rèn)構(gòu)造。
defaultdict要求我們?cè)跇?gòu)造時(shí)指定一個(gè)類型,然后會(huì)自動(dòng)根據(jù)需要初始化value。這樣我們就可以使用簡單的代碼來實(shí)現(xiàn)很多功能。
下面的代碼,我對(duì)比了使用defaultdict和original dict實(shí)現(xiàn)將學(xué)生按照姓的首字母分組的功能,以及分類計(jì)數(shù)的功能。
import collections
students = ['Zhang San', 'Li Si', 'Zhou liu', 'Chen qi', 'Cheng ba']
# using defaultdict
dd = collections.defaultdict(list)
for s in students:
key = s[0]
dd[key].append(s)
print(dd)
# using original dict (method 1)
od = {}
for s in students:
key = s[0]
if key not in do:
od[key] = []
od[key].append(s)
print(od)
scores = ['A', 'B', 'C', 'A', 'A', 'B', 'C', 'B', 'A', 'A']
# using defaultdict
dd = collections.defaultdict(int)
for s in scores :
dd[s] += 1
print(dd)
# using original dict (method 2)
od = collections.defaultdict(int)
for s in scores :
if s not in do:
do[s] = 1
else:
do[s] += 1
print(od)
Named Tuple
編程實(shí)踐中我們經(jīng)常需要?jiǎng)?chuàng)建一些小的數(shù)據(jù)結(jié)構(gòu)用來整合一組相關(guān)聯(lián)的數(shù)據(jù),簡單的比如地理坐標(biāo)的經(jīng)緯度,顏色的RGB值或者矩形框的左上和右下坐標(biāo),復(fù)雜的比如構(gòu)造一個(gè)窗口的一組參數(shù)。
實(shí)踐中,我們通常有3中實(shí)現(xiàn)方法:
- 對(duì)每一個(gè)這樣的數(shù)據(jù)結(jié)構(gòu)創(chuàng)建一個(gè)class。優(yōu)點(diǎn)是可以直接使用名字訪問數(shù)據(jù)成員,而且支持復(fù)雜的訪問邏輯和數(shù)據(jù)操作。缺點(diǎn)是需要編寫對(duì)應(yīng)的類和必須的函數(shù),管理文件和引用關(guān)系。
- 使用tuple。優(yōu)點(diǎn)是編寫簡單,內(nèi)存使用效率高。缺點(diǎn)是只能使用下標(biāo)訪問,可讀性差,容易出錯(cuò)。
- 使用dict,用str來作為對(duì)于屬性的名字。優(yōu)點(diǎn)是編寫相對(duì)簡單,而且保留了變量的名字。缺點(diǎn)是需要使用字符串表示名字較為麻煩,而且每一個(gè)結(jié)構(gòu)都要保存作為名字的字符串,浪費(fèi)空間。
collections的nametuple可以為我們直接構(gòu)造一個(gè)具有名字的簡單類型,方便快捷地實(shí)現(xiàn)類似手寫了一個(gè)class的效果。
需要注意的是collections.nametuple是一個(gè)factory function,它用來幫我們創(chuàng)建一個(gè)類型,而不是這個(gè)類型的具體對(duì)象。創(chuàng)建類型時(shí),我們可以指定各個(gè)屬性的名字,之后就可以使用.來訪問了,而且它同時(shí)還支持使用下標(biāo)訪問。同時(shí)Named Tuple還支持_asdict函數(shù)用來將內(nèi)部的數(shù)值轉(zhuǎn)換成一個(gè)dict。
# class
class Rect:
def __init__(self, x1, y1, x2, y2):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
def area_class(r):
w = r.x2 - r.x1
h = r.y2 - r.y1
return w*h
r1 = Rect(1,3,5,5)
# <__main__.Rect object at 0x7fde252a87f0>
# to show its content, we need to implement __repr__(self) or __str__(self)
print(area_class(r1))
# tuple
def area_tuple(r):
w = r[2]-r[0]
h = r[3]-r[1]
return w*h
r2 = (1,3,5,5)
print(r2)
# (1, 3, 5, 5)
print(area_tuple(r2))
# dict
def area_dict(r):
w = r["x2"] - r["x1"]
h = r["y2"] - r["y1"]
return w*h
r3 = {"x1":1, "y1":3, "x2":5, "y2":5}
print(r3)
# {'x1': 1, 'y1': 3, 'x2': 5, 'y2': 5}
print(area_tuple(r3))
# named tuple
import collections
Rectangle = collections.namedtuple("Rectangle", ["x1", "y1", "x2", "y2"])
def area_namedtuple(r):
w = r.x2 - r.x1
y = r.y2 - r.y1
return w*h
r4 = Rectangle(1,3,5,5)
print(r4)
# Rectangle(x1=1, y1=3, x2=5, y2=5)
x1,y2,x2,y2 = r4
print(x1,y2,x2,y2)
# 1 3 5 5
print(area_namedtuple(r4))
print(area_class(r4)) # work with "." grammar
print(area_tuple(r4)) # work with index
print(area_dict(r4._asdict())) # work with dict
Counter
顧名思義,Counter是用來對(duì)元素進(jìn)行計(jì)數(shù)的,它也是collections這個(gè)包里的。根據(jù)Python的官方文檔,它是dict類型的一個(gè)子類。
在構(gòu)造的時(shí)候輸入一個(gè)iterable的類型,比如list,range或是一個(gè)mapping的類型,比如dict,defaultdict。然后Counter就會(huì)對(duì)其中的元素進(jìn)行計(jì)數(shù)。
比較特殊的是,Counter對(duì)負(fù)數(shù)沒有做特殊處理,就是說在特殊操作下允許出現(xiàn)測(cè)試為負(fù),后面我們會(huì)有例子。
c = Counter() # a new, empty counter
c = Counter('gallahad') # a new counter from an iterable
print(c)
# Counter({'a': 3, 'l': 2, 'g': 1, 'h': 1, 'd': 1})
c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping
print(c)
# Counter({'red': 4, 'blue': 2})
c = Counter(cats=4, dogs=8) # a new counter from keyword args
print(c)
# Counter({'dogs': 8, 'cats': 4})
除了基本的計(jì)數(shù)功能,它還支持一些常用的相關(guān)功能。比如:
- 按照頻率排序(most_common([n]))。其中n是可選輸入,表示返回前n個(gè)最頻繁的元素和他們的頻率。默認(rèn)情況下返回所有的元素。
- 按照頻率輸出元素本身(elements())。它會(huì)返回元素本身,但是元素的順序不是原來的,相同的元素會(huì)連續(xù)輸出。不同元素之間,按照他們的出現(xiàn)順序輸出,這一點(diǎn)是OrderedDict以及3.7之后的dict所提供的特性。
- 兩個(gè)Counter相減(substract(c))。它可以從第一個(gè)counter上減去第二個(gè)counter中對(duì)應(yīng)元素出現(xiàn)的次數(shù)。對(duì)于只出現(xiàn)在第二個(gè)coutner中元素,默認(rèn)其在第一個(gè)counter中出現(xiàn)0次。
c = Counter(a=4, b=2, c=0, d=-2)
sorted(c.elements())
# ['a', 'a', 'a', 'a', 'b', 'b']
Counter('abracadabra').most_common(3)
# [('a', 5), ('b', 2), ('r', 2)]
c1 = Counter(a=4, b=2, d=-2)
c2 = Counter(a=1, b=2, c=3, d=4)
c1.subtract(c2)
c1
# Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
更多的參考信息大家可以參考官方文檔:
https://docs.python.org/3/library/collections.html
以上就是4種非常實(shí)用的python內(nèi)置數(shù)據(jù)結(jié)構(gòu)的詳細(xì)內(nèi)容,更多關(guān)于python內(nèi)置數(shù)據(jù)結(jié)構(gòu)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Python基礎(chǔ)之?dāng)?shù)據(jù)結(jié)構(gòu)詳解
- python中常用的數(shù)據(jù)結(jié)構(gòu)介紹
- python實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)中雙向循環(huán)鏈表操作的示例
- Python描述數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí)之哈夫曼樹篇
- 淺談Python描述數(shù)據(jù)結(jié)構(gòu)之KMP篇
- 基于python實(shí)現(xiàn)模擬數(shù)據(jù)結(jié)構(gòu)模型
- Python數(shù)據(jù)結(jié)構(gòu)dict常用操作代碼實(shí)例
- 基于Python數(shù)據(jù)結(jié)構(gòu)之遞歸與回溯搜索
- 淺析Python語言自帶的數(shù)據(jù)結(jié)構(gòu)有哪些
- Python 實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)-堆棧和隊(duì)列的操作方法
- Python 實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)-循環(huán)隊(duì)列的操作方法
相關(guān)文章
django+js+ajax實(shí)現(xiàn)刷新頁面的方法
這篇文章主要介紹了django+js+ajax實(shí)現(xiàn)刷新頁面的方法,結(jié)合實(shí)例形式分析了django實(shí)現(xiàn)ajax刷新頁面功能的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-05-05
Python實(shí)現(xiàn)多條件篩選目標(biāo)數(shù)據(jù)功能【測(cè)試可用】
這篇文章主要介紹了Python實(shí)現(xiàn)多條件篩選目標(biāo)數(shù)據(jù)功能,結(jié)合實(shí)例形式總結(jié)分析了Python3使用內(nèi)建函數(shù)filter、pandas包以及for循環(huán)三種方法對(duì)比分析了列表進(jìn)行條件篩選操作相關(guān)實(shí)現(xiàn)技巧與運(yùn)行效率,需要的朋友可以參考下2018-06-06
python輸出結(jié)果刷新及進(jìn)度條的實(shí)現(xiàn)操作
這篇文章主要介紹了python輸出結(jié)果刷新及進(jìn)度條的實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07
Python中的sorted函數(shù)應(yīng)用及文件操作詳解
這篇文章主要介紹了Python中的sorted函數(shù)應(yīng)用及文件操作詳解,python只能將字符串寫入到文本文件,要將數(shù)值數(shù)據(jù)存儲(chǔ)到文本本件中,必須先試用函數(shù)str()將其轉(zhuǎn)換為字符串格式,需要的朋友可以參考下2023-12-12
Matplotlib子圖的創(chuàng)建的實(shí)現(xiàn)
本文主要介紹了Matplotlib子圖的創(chuàng)建的實(shí)現(xiàn),包括fig.add_axes()創(chuàng)建子圖和plt.axes創(chuàng)建子圖這兩種方法,具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11
python 中 .py文件 轉(zhuǎn) .pyd文件的操作
這篇文章主要介紹了python 中 .py文件 轉(zhuǎn) .pyd文件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03
MacOS安裝python報(bào)錯(cuò)"zsh:?command?not?found:python"的
這篇文章主要給大家介紹了關(guān)于MacOS安裝python報(bào)錯(cuò)"zsh:?command?not?found:python"的解決方法,文中將解決的辦法介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02

