Python 簡明教程 --- 14,Python 數據結構進階

微信公衆號:碼農充電站pro
我的主頁:https://codeshellme.github.iohtml

若是你發現特殊狀況太多,那極可能是用錯算法了。
—— Carig Zerounipython

目錄git

在這裏插入圖片描述

前幾節咱們介紹了Python 中四種數據結構的特性和基本用法,本節介紹與數據結構相關的高級特性。github

  • 序列
  • 迭代器
  • 列表生成式
  • 生成器
  • 強制類型轉換

1,序列

Python 序列是指,其中存放的元素是有序排列的,可用下標訪問,字符串列表元組都是序列。算法

字典集合中的元素是無序排列的,所以通常不歸在序列中。shell

Python 序列有以下特色:微信

  • 序列中的元素是不可變類型
  • 序列中的元素可用下標訪問,下標可正可負
  • 可經過切片訪問部分連續元素
  • 可進行相加相乘in 運算
  • 可經過for 循環遍歷全部元素

可使用collections 模塊中的Sequence 類來查看一個對象是不是一個序列:數據結構

>>> isinstance('', collections.Sequence) # 字符串是序列
True
>>> isinstance([], collections.Sequence) # 列表是序列
True
>>> isinstance((), collections.Sequence) # 元組是序列
True
>>> isinstance({}, collections.Sequence) # 字典不是序列
False
>>> isinstance(set(), collections.Sequence) # 集合不是序列
False

提示:app

1,isinstance 函數用於查看一個對象屬於某個類函數

2,在使用模塊時,要先import 該模塊

2,迭代器

可迭代類型

咱們知道strlisttupledictset 均可用for 循環來遍歷,這個遍歷的過程就是一個迭代過程,這些類型都是可迭代類型。

可迭代的類型,都實現了__iter__ 方法,咱們經過dir(可迭代對象),能夠看到,可迭代對象的魔法方法中都有一個__iter__ 方法。

咱們也能夠經過collections 模塊中的Iterable 類型來查看一個對象是否是可迭代對象:

>>> isinstance('', collections.Iterable)
True
>>> isinstance([], collections.Iterable)
True
>>> isinstance((), collections.Iterable)
True
>>> isinstance({}, collections.Iterable)
True
>>> isinstance(set(), collections.Iterable)
True

迭代器

迭代器是一種可迭代的對象。

迭代器必定是可迭代的,可迭代的對象不必定是迭代器。

迭代器要實現兩個魔法方法:__iter____next__

經過collections 模塊中的Iterator 類型來查看這兩個方法:

>>> dir(collections.Iterator)

判斷一個對象是否是迭代器:

>>> isinstance('', collections.Iterator) # 字符串不是迭代器
False
>>> isinstance([], collections.Iterator) # 列表不是迭代器
False
>>> isinstance((), collections.Iterator) # 元組不是迭代器
False
>>> isinstance({}, collections.Iterator) # 字典不是迭代器
False
>>> isinstance(set(), collections.Iterator) # 集合不是迭代器
False

迭代器通用函數

迭代器有一些通用函數,下面咱們介紹一些經常使用的。

1.enumerate 函數

在Python3 中,enumerate 其實是一個,可經過help(enumerate) 查看,也能夠把它當作函數來使用。

其常常被用在for 循環中,便可遍歷下標,又能遍歷數據。

做用: 用於給一個可迭代的對象,添加下標
原型: enumerate(iterable[, start]) -> iterator
參數 iterable: 一個可迭代的對象
參數 start: 下標起始位置
返回值: 一個enumerate 對象,同時也是一個迭代器

示例:

>>> l = enumerate(['a', 'c', 'b']) # 參數是一個列表
>>> type(l)
<class 'enumerate'>
>>> isinstance(l, collections.Iterator) # 是一個迭代器
True
>>> for index, item in l:           # for 循環遍歷,能遍歷出下標
...     print(index, item)
... 
0 a
1 c
2 b

2.iter 函數

做用:將一個可迭代的序列iterable 轉換成迭代器
原型:iter(iterable) -> iterator
參數:iterable 是一個可迭代的序列
返回值:一個迭代器

示例:

>>> iter('123')            # 參數是字符串
<str_iterator object at 0x7fcb7dd320b8>     # str 迭代器
>>> iter([1, 2, 3])        # 參數是列表
<list_iterator object at 0x7fcb7dd4a0b8>    # list 迭代器
>>> iter((1, 2, 3))        # 參數是元組
<tuple_iterator object at 0x7fcb7dd4a0b8>   # tuple 迭代器
>>> iter(set([1, 2, 3]))   # 參數是集合
<set_iterator object at 0x7fcb7d2c5e10>     # set 迭代器
>>> iter({'a':1, 'b':2})   # 參數是字典
<dict_keyiterator object at 0x7fcb7f467098> # dict 迭代器

3.next 函數

做用:返回迭代器的下一個元素
原型:next(iterator[, default]) -> item
參數 iterator:是一個迭代器類型
參數 default:任意類型數據,可省
返回值

迭代器中有元素時:返回迭代器中的下一個元素
迭代器中沒有元素沒有default 參數時:拋出StopIteration 異常
迭代器中沒有元素有default 參數時:返回default

示例:

>>> i = iter([1, 3, 5])  # i 是一個迭代器
>>> next(i)              # 返回 1
1
>>> next(i)              # 返回 3
3
>>> next(i)              # 返回 5
5
>>> next(i)              # i 中沒有元素,拋出異常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> 
>>> next(i, 7)           # i 中沒有元素,返回第二個參數 7
7

4.len 函數

做用:用於計算一個對象obj中的元素的個數
原型:len(obj, /)
參數:通常obj 是一個可迭代類型對象,實際上,只要實現了__len__ 方法的對象,均可以使用該函數
返回值:一個整數

示例:

>>> len('abc')
3
>>> len([1, 2, 3])
3

5.max 函數

做用:返回可迭代對象iterable 中的最大元素
原型:max(iterable)
參數iterable 是一個可迭代的對象,而且iterable 中的元素可比較
返回值:最大值

示例:

>>> max([1, 2])
2
>>> max([1, 2, 3])
3
>>> max('b', 'a')
'b'
>>> max('abc')
'c'
>>> max(1, 'a')     # 整數與字符串不是同類型,不可比較
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'int'

6.min 函數

做用:返回可迭代對象iterable 中的最小元素
原型:min(iterable)
參數iterable 是一個可迭代的對象,而且iterable 中的元素可比較
返回值:最小值

示例:

>>> min([1, 2])
1
>>> min([2, 3])
2
>>> min('abc')
'a'
>>> min('b', 'c')
'b'
>>> min('b', 2)  # 整數與字符串不是同類型,不可比較
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'

7.sum 函數

做用:計算可迭代對象iterable 中的數據之和,最後在加上 start
原型:sum(iterable, start=0, /)
參數iterable 是一個可迭代對象,其中的元素是數字類型
返回值:全部元素之和

示例:

>>> sum([1, 2, 3])     # 計算 1,2,3 之和
6
>>> sum([1, 2, 3], 5)  # 計算 1,2,3 之和,再加上 5
11

8.reversed 函數

reversed 其實是一個類,可用help(reversed) 查看。

做用:將一個序列sequence 反轉
原型:reversed(sequence)
參數sequence 是一個序列類型
返回值:一個reversed 對象,該對象也是一個迭代器,可被迭代

示例:

>>> r = reversed('abcde')
>>> r                                    # 一個 reversed 對象
<reversed object at 0x7fcb79970518>
>>> isinstance(r, collections.Iterator)  # 也是一個迭代器
True
>>> [i for i in r]                  # 轉換成列表,查看其中的元素
['e', 'd', 'c', 'b', 'a']
>>>
>>> r = reversed([1, 3, 5, 7])
>>> [i for i in r]
[7, 5, 3, 1]

3,列表生成式

列表生成式,又叫列表推導式,用於從一個可迭代對象生成一個列表,它是一種代碼簡寫形式,其優勢是代碼簡潔優雅。

好比,咱們有一個列表 [1, 3, 5],想求其中每一個元素的平方,再將結果放入列表中,最終的結果是[1, 9, 25]

若是是通常的方式,咱們寫出來的代碼是這樣的:

l = [1, 3, 5]

l2 = []
for i in l:
    item = i * i 
    l2.append(item)

print(l2)

若是用列表生成式的方式,代碼是這樣的:

l = [1, 3, 5]

l2 = [i * i for i in l]

print(l2)

能夠看到列表生成式比普通的形式要簡潔許多。

列表生成式語法

最簡單的列表生成式的語法,就像上面的代碼同樣:

在這裏插入圖片描述

列表生成式由三部分組成:

  • 列表符號:中括號[]
  • 表達式:用於生成新列表中的每一個元素,通常與item 有關,也可無關
  • for 循環:用於迭代原始可迭代對象

列表生成式中的if 判斷

列表生成式中也能夠有if 判斷,當判斷條件成立時,纔會執行表達式,並將該表達式的結果append 到新的列表中。

這裏的if 判斷沒有else 部分,判斷條件通常與item 有關。

以下:

在這裏插入圖片描述

示例:

l = [1, 3, 5]

# 只有當 l 中的元素大於 1 時,纔算平方
l2 = [i * i for i in l if i > 1]

print(l2)

range 函數

Python2.x 中range 是一個函數

Python3.x 中,range 是一個,可用help(range) 查看其手冊。

>>> range
<class 'range'>

下面介紹Python3.xrange 的用法,有兩種參數形式:

做用:生成一個從startstop 的,步長爲step 的,可迭代的整數序列,該序列包含start,不包含stop,即遵循左開右閉原則
原型

range(stop) -> range object
range(start, stop[, step]) -> range object

參數

當只有stop 參數時,該序列從0 開始到stop,步長爲1
當有startstop 參數時,該序列從start 開始到stop,步長爲1
當有step 參數時,步長爲step

返回值:一個range 對象

示例:

>>> range(5)
range(0, 5)
>>> range(1, 5)
range(1, 5)
>>> range(1, 5, 2)
range(1, 5, 2)

range 對象是一個序列,而不是一個迭代器:

>>> isinstance(range(5), collections.Sequence)
True
>>> isinstance(range(5), collections.Iterator)
False

可使用列表生成式來查看range 中的內容:

>>> [i for i in range(5)]       # 從 0 到 5
[0, 1, 2, 3, 4]
>>> [i for i in range(1, 5)]    # 從 1 到 5
[1, 2, 3, 4]
>>> [i for i in range(1, 5, 2)] # 步長爲 2
[1, 3]

4,生成器

生成器也是一個迭代器。生成器跟列表有點像,但優勢是比列表節省內存

對於列表,Python 會爲列表中的每一個元素都分配實實在在的內存空間,若是列表中的元素不少,那麼列表將消耗大量內存。

而對於生成器,Python 並不會爲其中的每一個元素都分配內存。

生成器記錄的是一種算法,是如何生成數據的算法,在每次用到數據時,纔會去生成數據,而不會一開始就將全部的數據準備好。

所以,對於相同的功能,生成器列表都能完成,而生成器能夠節省大量的內存。

建立生成器有兩種方式:

  • 列表生成式中的中括號[]改成小括號()
  • 在函數中使用yield 關鍵字

使用列表生成式

以下代碼能夠生成一個列表:

>>> [i for i in range(5)]
[0, 1, 2, 3, 4]

將中括號[] 改成小括號(),就是一個生成器:

>>> l = (i for i in range(5))
>>> l
<generator object <genexpr> at 0x7f3433d2d9e8>
>>> type(l)
<class 'generator'>
>>> isinstance(l, collections.Iterator) # 生成器也是一個迭代器
True

其中的generator 就是生成器的意思,它也是一個

使用yield 關鍵字

好比,咱們想計算列表[1, 3, 5] 中每一個元素的平方,使用yield 關鍵字,代碼以下:

#! /usr/bin/env python3

def test():
    print('test...')
    l = [1, 3, 5]

    for i in l:
        tmp = i * i 
        print('yield tmp:%s' % tmp)
        yield tmp 

t = test()
print(t)       # <generator object test at 0x7fde1cdaa3b8> 
print(type(t)) # <class'generator'>

注意,咱們定義了一個函數,這裏咱們只是爲了演示如何使用yield 來建立生成器,而不用過多關注如何定義函數。

函數的概念咱們會在後續章節詳細介紹。

執行以上代碼,輸出以下:

<generator object test at 0x7fde1cdaa3b8> 
<class'generator'>

你會發現,字符串test...並無被打印出來。

你可能會有疑問,既然代碼t = test() 已經執行了,那整個test() 函數中的代碼都應該執行完了纔對,那字符串test... 怎麼會沒有打印呢?

那是由於,生成器中代碼的執行是惰性的。當執行t = test() 這行代碼時,test() 函數並無被執行。

前邊咱們說過,生成器記錄的是一個算法,而不是真正的數據,數據只有當使用到的時候,纔會去生成。

因此,變量 t 中只是一個算法,而沒有數據。

由於,生成器也是一個迭代器,因此生成器可使用next() 函數來訪問其中的數據:

i = next(t)
print('i value is', i)

執行上面這行代碼後,程序會輸出:

test...
yield tmp:1
i value is 1

字符串test... 被打印,說明test() 執行了。

當代碼執行到yield 時,變量i 會接收到yield 返回的數據,此時,代碼會從yield 處跳出test() 函數。

若是接下來,再也不遍歷變量t 中的數據,那麼整個代碼就執行結束了。

若是咱們再次執行代碼:

j = next(t)
print('j value is', j)

程序會輸出:

yield tmp:9
j value is 9

可見代碼會在上次yield 的地方,再次向下執行。

咱們再次執行代碼:

k = next(t)
print('k value is', k)

程序會輸出:

yield tmp:25
k value is 25

t 中的元素被遍歷完後,若是再次執行next(t),則會拋出StopIteration 異常。

使用next() 函數來遍歷生成器中的全部元素是很麻煩的,咱們能夠像遍歷列表同樣,用for 循環來遍歷生成器中的元素:

for i in t:
    print(i)

輸出以下:

test...
yield tmp:1
1
yield tmp:9
9
yield tmp:25
25

整個遍歷過程當中,字符串test... 只被輸出了一次,並無被輸出三次。

說明當代碼執行到yield 時,並無從函數test() 中返回,代碼只是暫停在了yield 處,等下次須要數據時,會接着從上次的yield 處接着執行。

生成器比列表節省內存

若是咱們想生成一個從09999 的數字序列,用列表的話,是這樣的:

>>> l = [i for i in range(10000)]
>>> sys.getsizeof(l)  # 內存佔用 87624 字節
87624

sys 模塊的getsizeof 方法能夠查看一個對象的大小,單位是字節

用生成器來實現的話,是這樣的:

>>> l = (i for i in range(10000))
>>> sys.getsizeof(l)  # 內存佔用 88 字節
88

能夠看到09999 這樣的整數序列,使用列表的話,佔用 87624 字節;使用生成器的話,只佔用 88 字節

5,強制類型轉換

咱們已經知道了,Python3 中的strlisttupledictset 都是一個類:

>>> type('')
<class 'str'>
>>> type([])
<class 'list'>
>>> type(())
<class 'tuple'>
>>> type({})
<class 'dict'>
>>> type(set())
<class 'set'>

每一個類都有構造方法,這些構造方法能夠將其它類型的數據,轉換成該類型數據,咱們也能夠將這種轉換稱爲強制類型轉換

提示:

構造方法是一個的初始化方法,就是用什麼樣的數據去構造一個特定類的對象。

當介紹到類與對象時,咱們會詳細介紹。

str強制轉換

做用: 將其它類型數據轉換成字符串
原型: str(object='') -> str
參數: 任意類型數據
返回值: 字符串

示例:

>>> str(1)        # 將數字轉換成字符串
'1'
>>> str([1, 2])   # 將列表轉換成字符串
'[1, 2]'
>>> str((1, 2))   # 將元組轉換成字符串
'(1, 2)'

list強制轉換

做用: 將一個可迭代類型轉成列表
原型: list(iterable) -> list
參數: 任意可迭代類型數據
返回值: 列表

示例:

>>> list((1, 2))   # 將一個元組轉成列表
[1, 2]
>>> list(range(3)) # 將一個 range 對象轉成列表
[0, 1, 2]

tuple強制轉換

做用: 將一個可迭代類型轉成元組
原型: tuple(iterable) -> tuple
參數: 任意可迭代類型數據
返回值: 元組

示例:

>>> tuple([1, 2])    # 將一個列表轉成元組
(1, 2)
>>> tuple(range(3))  # 將一個 range 對象轉成元組
(0, 1, 2)

dict強制轉換

做用: 將一個可迭代類型數據轉成字典
原型: dict(iterable) -> dict
參數: iterable 是一個可迭代對象,而且該對象中的元素是元組
返回值: 字典

示例:

>>> t = ((1, 2), (2, 3))  # t 是一個元組,其中的元素也是元組
>>> dict(t)
{1: 2, 2: 3}
>>> 
>>> l = [(1, 2), (2, 3)] # l 是一個列表,其中的元素是元組
>>> dict(l)
{1: 2, 2: 3}

set強制轉換

做用: 將一個可迭代類型數據轉成集合
原型: set(iterable) -> set
參數: 一個可迭代對象
返回值: 集合

其實,咱們在介紹集合時,都是用的這種方式來聲明的集合,示例:

>>> set('abc')      # 將一個字符串轉成集合
{'b', 'c', 'a'}
>>> set([0, 1])     # 將一個列表轉成集合
{0, 1}
>>> set((0, 1))     # 將一個元組轉成集合
{0, 1}

(完。)


推薦閱讀:

Python 簡明教程 --- 9,Python 編碼

Python 簡明教程 --- 10,Python 列表

Python 簡明教程 --- 11,Python 元組

Python 簡明教程 --- 12,Python 字典

Python 簡明教程 --- 13,Python 集合


歡迎關注做者公衆號,獲取更多技術乾貨。

碼農充電站pro

相關文章
相關標籤/搜索