Python中有6種基本的數(shù)據(jù)類型,除了數(shù)字類型,其它5種類型都是可迭代對(duì)象
。掌握可迭代對(duì)象的特性和方法是非常有必要的。
創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),嵊州企業(yè)網(wǎng)站建設(shè),嵊州品牌網(wǎng)站建設(shè),網(wǎng)站定制,嵊州網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,嵊州網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
迭代(遍歷)
就是按照某種順序逐個(gè)訪問對(duì)象中的每一項(xiàng)。
Python中有很多對(duì)象都是可以通過for語句來直接遍歷的,例如list、string、dict等等,這些對(duì)象都是可迭代的,被稱為可迭代對(duì)象。
可以將可迭代對(duì)象想象成一個(gè)容器,里面存放了有限個(gè)元素,并且每個(gè)元素都可以從中獲取出來。那么這個(gè)容器就是可迭代的,這個(gè)容器就是可迭代對(duì)象。
所有的可迭代對(duì)象都需要實(shí)現(xiàn)__iter__
方法,該方法就是用于當(dāng)我們?cè)谘h(huán)時(shí)將可迭代對(duì)象
轉(zhuǎn)換成迭代器
的。
from typing import *
dct = {'one': 1, 'two': 2, 'three': 3, 'zero': 0}
print(isinstance(dct, Iterable))
True
迭代器
是可迭代對(duì)象
的一個(gè)子集。是一個(gè)可以記住遍歷的位置的對(duì)象,它與列表、元組、集合、字符串這些可迭代對(duì)象
的區(qū)別就在于__next__()
方法的實(shí)現(xiàn)。也就是通過該方法可以一個(gè)個(gè)的將元素取出來。
迭代器支持__iter__()
和__next__()
方法。其中:
__iter__()
方法返回迭代器對(duì)象本身,而可迭代對(duì)象的該方法則返回其迭代器。
__next__()
方法返回容器的下一個(gè)元素,在結(jié)尾時(shí)引發(fā)StopIteration異常。
遍歷的本質(zhì)其實(shí)就是在我們使用for或者while循環(huán)可迭代對(duì)象時(shí)會(huì)自動(dòng)調(diào)用該可迭代對(duì)象的__iter__()方法得到其迭代器,然后通過這個(gè)迭代器的__next__()方法一步步獲取下一個(gè)元素。直到最后一個(gè)元素引發(fā)StopIteration異常。
對(duì)于迭代器,其__next__()方法和next(迭代器)等效,都是用來獲取下一個(gè)元素。
通過iter函數(shù)可以很簡單的將可迭代對(duì)象轉(zhuǎn)換成迭代器。
示例1:
>>> from typing import *
>>> iterable = [1, 2, 4]
>>> it = iter(iterable)
>>> print(isinstance(it, Iterable)) # 是否可迭代對(duì)象
>>> print(isinstance(it, Iterator)) # 是否迭代器
True
True
示例2:
s = 'ABC' # s此時(shí)是一個(gè)可迭代對(duì)象
it = iter(s) # 轉(zhuǎn)換成迭代器,如果此時(shí)報(bào)錯(cuò),則表示s不是一個(gè)可迭代對(duì)象。
for i in range(len(s)):
print(s[i]) # 遍歷s中的所有元素
print(it.__next__)
print(it.__next__()) # 迭代獲取元素
print(next(it)) # 繼續(xù)迭代獲取元素
A
B
C
next' of str_iterator object at 0x0000013DD40>
A
B
參見可迭代對(duì)象相關(guān)函數(shù)
的filter函數(shù)
參見可迭代對(duì)象相關(guān)函數(shù)
的map函數(shù)
除了Python內(nèi)置的iter之外,還可以通過Python內(nèi)置的工具包itertools創(chuàng)建迭代器,其中函數(shù)包括:
count
cycle
repeat
accumulate
chain
compress
dropwhile
islice
product
permutations
combinations
......
itertools中包含很多用于創(chuàng)建迭代器的實(shí)用方法,如果感興趣可以訪問官方文檔進(jìn)行詳細(xì)了解。
class iterator_list(object):
def __init__(self,a):
self.a=a
self.len=len(self.a)
self.cur_pos=-1
def __iter__(self):
return self
def __next__(self):
self.cur_pos +=1
if self.cur_pos
r = iter(range(10))
print(5 in r)
for i in r:
print(i)
True
6
7
8
9
r = iter(range(10))
print(5 in r)
print(5 in r)
True
False
r = iter(range(10))
print(11 in r)
for i in r:
print(i)
False
你的數(shù)據(jù)量過大,大到足以撐爆你的內(nèi)存或者你以節(jié)省內(nèi)存為首選因素時(shí),將數(shù)據(jù)集設(shè)置為迭代器是一個(gè)不錯(cuò)的選擇,節(jié)省內(nèi)存,按需取值。
生成器
是迭代器
的子集,生成器一定是迭代器,但是迭代器不全是生成器。在Python中一個(gè)函數(shù)可以用yiled或yiled from替代return返回值,這樣的話這個(gè)函數(shù)就變成了一個(gè)生成器對(duì)象。
可以通過isinstance(obj, Generator)來進(jìn)行判斷是否為迭代器(需要導(dǎo)入typing模塊)。
通過yield
def fib(number):
n, a, b = 0, 0, 1
while n < number:
yield b
a, b = b, a + b
n += 1
gen = fib(5)
print(gen)
print(type(gen))
def func():
print('111')
yield 222
print('123')
yield 1211
gener = func()
print(gener.__next__())
print(gener.__next__())
print(gener.__next__()) # 會(huì)報(bào)錯(cuò)
111
222
123
1211
Traceback (most recent call last):
File "C:\Users\furongbing\PycharmProjects\pythonProject\t2.py", line 11, in
print(gener.next()) # 會(huì)報(bào)錯(cuò)
StopIteration
通過yield from
def generator(array): # 其中:array為可迭代對(duì)象
for sub_array in array:
yield from sub_array
gen = generator([1, 2, 3])
print(gen)
print(type(gen))
yield from相對(duì)于yield的有幾個(gè)主要優(yōu)點(diǎn):
yield 與 return 的區(qū)別:
>>> gen = (x*2 for x in range(10))
>>> gen
>>> type(gen)
列表推導(dǎo)式和生成器推導(dǎo)式的區(qū)別:
生成器的優(yōu)點(diǎn):
可迭代對(duì)象
都可以進(jìn)行遍歷的操作。就是將其中的元素一個(gè)個(gè)取出來進(jìn)行操作。
Iter = 'Python'
for i in Iter:
print(i)
P
y
t
h
o
n
對(duì)于序列
,不但能遍歷里面所有的元素,還能遍歷元素的索引。關(guān)于序列,將在序列
中詳細(xì)介紹。
用range()和len()函數(shù)遍歷得到索引和值
seq = 'Python'
for i in range(len(seq)):
print(f'索引:{i}, 元素:{seq[i]}')
索引:0, 元素:P
索引:1, 元素:y
索引:2, 元素:t
索引:3, 元素:h
索引:4, 元素:o
索引:5, 元素:n
通過enumerate函數(shù)遍歷得到索引和值
seq = 'Python'
for i, v in enumerate(seq):
print(f'索引:{i}, 元素:{v}')
索引:0, 元素:P
索引:1, 元素:y
索引:2, 元素:t
索引:3, 元素:h
索引:4, 元素:o
索引:5, 元素:n
使用zip函數(shù)同時(shí)遍歷多個(gè)序列
seq1 = 'Python'
seq2 = 'Java'
for q, a in zip(seq1, seq2):
print(q, a)
P J
y a
t v
h a
注意:上述用字符串做演示,實(shí)際上其它序列對(duì)象也是一樣的
可以用in
和not in
檢查某個(gè)元素是否在目標(biāo)可迭代對(duì)象中。可迭代對(duì)象
都支持成員資格檢查操作。
>>> Iter = 'Python'
>>> 'P' in Iter
>>> 'a' not in Iter
True
True
注意:上述用字符串做演示,實(shí)際上其它可迭代對(duì)象也是一樣的
解包的英文是unpacking,就是將容器里的元素全部取出來。在Python中,所有的可迭代對(duì)象都支持解包。有些情況中,解包會(huì)自動(dòng)完成,在另外一些情況中,可以手動(dòng)進(jìn)行解包。
裝包和解包相反,就是將一些元素打包放到一起。
在進(jìn)行變量賦值的時(shí)候,如果變量的數(shù)量和右邊可迭代對(duì)象中元素的數(shù)量相同時(shí),解包會(huì)自動(dòng)完成。
a, b = [1, 2]
print(a, b)
c, d = {'one': 1, 'two': 2}
print(c, d)
1 2
one two
我們?cè)谶M(jìn)行變量賦值的時(shí)候,經(jīng)常會(huì)用到下面這種方式,同時(shí)為不同的變量賦值不同的數(shù)據(jù):
>>> e, f = 5, 6
實(shí)際上這就是利用到了解包。后面的5, 6
其實(shí)就是可迭代對(duì)象(元組),然后進(jìn)行自動(dòng)解包后賦值給了變量e和f。
這里值得注意的是,字典在進(jìn)行自動(dòng)解包時(shí)獲得的是字典的key。
可以通過在可迭代對(duì)象前面添加*
符號(hào)進(jìn)行手動(dòng)解包,解包后的結(jié)果是可迭代對(duì)象中所包含的所有的元素。
因?yàn)槭嵌鄠€(gè)元素,所以不能對(duì)解包后的結(jié)果使用len等只支持單個(gè)參數(shù)的函數(shù)。否則會(huì)報(bào)錯(cuò)。但是可以使用max等可以接收多個(gè)參數(shù)的函數(shù)。
手動(dòng)解包一般是用在函數(shù)接收參數(shù)中。
lst = [1, 2, 4]
print(*lst)
print(max(*lst))
print(len(*lst))
1 2 4
4
Traceback (most recent call last):
File "E:\studypy\tmp5.py", line 4, in
print(len(*lst))
TypeError: len() takes exactly one argument (3 given)
在賦值或者函數(shù)傳參時(shí),如果在等式左邊變量名添加*
則可以進(jìn)行裝包。
lst = [1, 2, 4, 8, 16]
dct = {'one': 1, 'two': 2, 'three': 3, 'four': 4}
a, b, *c = lst
print(a, b, c)
d, *e, f = dct
print(d, e, f)
1 2 [4, 8, 16]
one ['two', 'three'] four
dct = {'one': 1, 'two': 2, 'three': 3, 'four': 4}
a, *b, c = dct.items()
print(a, b, c)
('one', 1) [('two', 2), ('three', 3)] ('four', 4)
用*
進(jìn)行裝包后的變量類型其實(shí)就是列表,在函數(shù)中則是元組。函數(shù)的解包與裝包將會(huì)在函數(shù)章節(jié)中詳細(xì)介紹。
描述
通過調(diào)用迭代器的__next__()方法從迭代器中檢索下一項(xiàng)。如果給出了默認(rèn)值,則在迭代器耗盡時(shí)返回默認(rèn)值,否則將引發(fā) StopIteration。
示例
a = iter([1, 2, 3])
print(next(a))
print(next(a))
print(next(a))
print(next(a, '無數(shù)據(jù)了'))
1
2
3
無數(shù)據(jù)了
描述
對(duì)于all函數(shù),如果 iterable 的所有元素均為真值或可迭代對(duì)象為空則返回 True。否則返回False。any函數(shù)則是只要有一個(gè)元素為真值,則返回True,否則返回False。若iterable為空,也返回False。
示例
a = []
b = [1, 2]
c = [1, 0]
d = [0, 0]
print(all(a))
print(all(b))
print(all(c))
print(all(d))
print(any(a))
print(any(b))
print(any(c))
print(any(d))
True
True
False
False
False
True
True
False
描述
返回一個(gè)枚舉對(duì)象。iterable 必須是一個(gè)序列,或 iterator,或其他支持迭代的對(duì)象。 enumerate() 返回的迭代器的 next() 方法返回一個(gè)元組,里面包含一個(gè)計(jì)數(shù)值(從 start 開始,默認(rèn)為 0)和通過迭代 iterable 獲得的值。
示例
dct = {'one': 1, 'two': 2}
for i, j in enumerate(dct):
print(i, j)
0 one
1 two
描述
將iterable中的元素作為function函數(shù)的輸入,然后將返回結(jié)果為真的元素構(gòu)建一個(gè)新的迭代器。
如果function是None,則會(huì)假設(shè)它是一個(gè)身份函數(shù),即iterable中所有返回假的元素會(huì)被移除。
請(qǐng)注意,filter(function, iterable)相當(dāng)于一個(gè)生成器表達(dá)式,當(dāng) function 不是None時(shí)等效為:(item for item in iterable if function(item))
function是None時(shí)等效為:(item for item in iterable if item)
示例
from typing import *
a = [1, 2, 3, 4]
r = filter(lambda x: x - 2, a)
print(list(r))
print(type(r))
print(isinstance(r, Iterable))
print(isinstance(r, Iterator))
print(isinstance(r, Generator))
[1, 3, 4]
True
True
False
描述
返回可迭代對(duì)象中包含的元素的個(gè)數(shù)。
示例
>>> len('string')
>>> len([1, 2, 3])
6
3
描述
返回一個(gè)將 function 應(yīng)用于 iterable 中每一項(xiàng)并輸出其結(jié)果的迭代器。 如果傳入了額外的 iterable 參數(shù),function 必須接受相同個(gè)數(shù)的實(shí)參并被應(yīng)用于從所有可迭代對(duì)象中并行獲取的項(xiàng)。 當(dāng)有多個(gè)可迭代對(duì)象時(shí),最短的可迭代對(duì)象耗盡則整個(gè)迭代就將結(jié)束。
示例
from typing import *
a = [1, 2, 3, 4]
b = [2, 4, 6, 8]
r = map(lambda x, y: x + y, a, b)
print(list(r))
print(type(r))
print(isinstance(r, Iterable))
print(isinstance(r, Iterator))
print(isinstance(r, Generator))
[3, 6, 9, 12]
True
True
False
描述
返回字符串中編號(hào)最大(最小)的字符。
示例
s = 'pythonTian賽車'
print(min(s))
print(max(s))
T
車
描述
從 start 開始自左向右對(duì) iterable 的項(xiàng)求和并返回總計(jì)值。 iterable 的項(xiàng)通常為數(shù)字,而 start 值則不允許為字符串。
實(shí)例
print(sum([1, 2, 3, 4]))
print(sum([1, 2, 3, 4], 3))
10
13
描述
在多個(gè)迭代器上并行迭代,從每個(gè)迭代器返回一個(gè)數(shù)據(jù)項(xiàng)組成元組。strict參數(shù)為True用來檢查所有的可迭代對(duì)象的長度是否一致,如果不一致則觸發(fā) ValueError。為False時(shí)則不檢查。
示例
for item in zip([1, 2, 3], ['sugar', 'spice', 'everything nice']):
print(item)
(1, 'sugar')
(2, 'spice')
(3, 'everything nice')
序列一定是可迭代對(duì)象,而可迭代對(duì)象不一定是序列。對(duì)于可迭代對(duì)象,如果元素是有序的,則是序列。
序列是一種特殊的可迭代對(duì)象,序列中的元素不僅可迭代,而且有順序,可以通過索引或切片的方式獲取序列中的元素。
Python中有6中基本的數(shù)據(jù)類型,其中字符串、列表、元組都是序列。
序列可以進(jìn)行拼接和重復(fù)以進(jìn)行擴(kuò)展。
使用'+'進(jìn)行拼接
通過+
可以將兩種相同類型的序列進(jìn)行拼接,并且拼接之后的數(shù)據(jù)類型是原來的類型。
>>> 'pyth' + 'on'
'python'
相鄰的2個(gè)字符串會(huì)自動(dòng)合并:
>>> 'pyt' 'hon'
'python'
>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> (1, 2, 3) + (4, 5, 6)
(1, 2, 3, 4, 5, 6)
使用'*'進(jìn)行重復(fù)
通過*
可以將兩種相同類型的序列進(jìn)行重復(fù),并且重復(fù)之后的數(shù)據(jù)類型是原來的類型。
>>> 'egg' * 3
'eggeggegg'
>>> [1, 2] * 2
[1, 2, 1, 2]
>>> (1, 2) * 2
(1, 2, 1, 2)
序列支持索引
(下標(biāo)訪問),第一個(gè)字符的索引是 0。之后每個(gè)元素的索引依次增加1。
>>> seq = 'Python'
>>> seq[0]
>>> seq[5]
'P'
'n'
索引還支持負(fù)數(shù),用負(fù)數(shù)索引時(shí),從右邊開始計(jì)數(shù):
>>> seq = 'Python'
>>> seq[-1]
>>> seq[-2]
>>> seq[-6]
'n'
'o'
'P'
注意,-0 和 0 一樣,因此,負(fù)數(shù)索引從 -1 開始。
索引位置參考下圖:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
索引越界會(huì)報(bào)錯(cuò):
>>> seq = 'Python'
>>> seq[42]
Traceback (most recent call last):
File "", line 1, in
IndexError: string index out of range
注意:上述用字符串做演示,實(shí)際上列表和元組也是一樣的
除了索引,序列還支持切片
。索引可以提取單個(gè)元素,切片則提取多個(gè)元素,參考下圖:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
注意:上面的數(shù)字對(duì)應(yīng)的是每個(gè)字符中間的分隔'|'線。
序列的切片語法格式如下:
序列[頭下標(biāo):尾下標(biāo)]
>>> seq = 'Python'
>>> seq[0:2]
>>> seq[2:5]
'Py'
'tho'
切片索引的默認(rèn)值很有用;省略開始索引時(shí),默認(rèn)值為 0,省略結(jié)束索引時(shí),默認(rèn)為到字符串的結(jié)尾:
>>> seq = 'Python'
>>> seq[:2]
>>> seq[4:]
>>> seq[-2:]
'Py'
'on'
'on'
注意,輸出結(jié)果包含切片開始,但不包含切片結(jié)束。因此,seq[:i] + seq[i:] 總是等于 seq:
>>> seq = 'Python'
>>> seq[:2] + string[2:]
>>> seq[:4] + string[4:]
'Python'
'Python'
對(duì)于使用非負(fù)索引的切片,如果兩個(gè)索引都不越界,切片長度就是起止索引之差。例如, seq[1:3] 的長度是 2。
切片會(huì)自動(dòng)處理越界索引:
>>> seq = 'Python'
>>> seq[4:42]
>>> seq[42:]
'on'
''
指定步長的切片
>>> seq = 'Python'
>>> seq[0:6:2] # 從第0個(gè)元素到第5個(gè)元素,每隔2個(gè)就提取一個(gè)出來
'Pto'
>>> seq[:] # 淺拷貝,結(jié)果同string
'Python'
>>> seq[::-1] # 翻轉(zhuǎn)整個(gè)字符串
'nohtyP'
步長為負(fù)數(shù)時(shí),先翻轉(zhuǎn)然后再每隔步長個(gè)字符就提取一個(gè)出來。
注意:
1、上述用字符串做演示,實(shí)際上列表和元組也是一樣的
2、字符串切片后返回的是字符串,同理,列表、元組切片后返回的也是列表、元組。
描述
返回str在seq里面出現(xiàn)的次數(shù)。未找到則返回0
示例
seq = ' Python tian \t mao \n taobao '
print(seq.count('o'))
print(seq.count('ao'))
print(seq.count('io'))
4
1
0
描述
返回str在seq里面出現(xiàn)的索引。未找到則報(bào)錯(cuò)。rindex表示從右邊開始查找。
示例
seq = ' Python tian \t mao \n taobao '
print(seq.index('o'))
print(seq.index('ao'))
print(seq.index('io'))
5
16
Traceback (most recent call last):
File "E:\studypy\tmp.py", line 4, in
print(s.index('io'))
ValueError: substring not found
描述
返回序列的反向序列的迭代器。經(jīng)過測試,對(duì)可迭代對(duì)象也生效。
示例
lst = [1, 2, 4]
re = reversed(lst)
print(re)
print(lst)
print(list(re))
[1, 2, 4]
[4, 2, 1]
描述
根據(jù) iterable 中的項(xiàng)返回一個(gè)新的已排序列表。具有兩個(gè)可選參數(shù),它們都必須指定為關(guān)鍵字參數(shù)。
key 指定帶有單個(gè)參數(shù)的函數(shù),用于從 iterable 的每個(gè)元素中提取用于比較的鍵 (例如 key=str.lower)。 默認(rèn)值為 None (直接比較元素)。
reverse 為一個(gè)布爾值。 如果設(shè)為 True,則每個(gè)列表元素將按反向順序比較進(jìn)行排序。
示例1:簡單排序
>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]
示例2:對(duì)元素調(diào)用函數(shù)排序
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']
示例3:將元素的某個(gè)索引作為key進(jìn)行排序
student_tuples = [
('john', 'A', 15),
('jane', 'B', 12),
('dave', 'B', 10),
]
r = sorted(student_tuples, key=lambda x: x[2], reverse=True)
print(r)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
多個(gè)關(guān)鍵字的排序
student_tuples = [
('john', 'A', 15),
('john', 'A', 20),
('jane', 'B', 12),
('dave', 'B', 10),
('dave', 'B', 5),
]
r = sorted(student_tuples, key=lambda x: (x[0], x[2]))
print(r)
[('dave', 'B', 5), ('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15), ('john', 'A', 20)]
更多排序的內(nèi)容可以參照:
Operator 模塊
排序