前言
??列表,元組,字典,集合,生成器都是python
中的可迭代對(duì)象,使用的時(shí)候經(jīng)常忘記,通過這篇博文總結(jié)一下。
一. 列表
??列表(list
)是Python
中的一種數(shù)據(jù)結(jié)構(gòu),它可以存儲(chǔ)不同類型的數(shù)據(jù)。不同元素以逗號(hào)分隔。
1.1. 使用規(guī)則
- 使用方括號(hào)[]表示開始和結(jié)束。
- 不同元素以逗號(hào)分隔。
- 每個(gè)元素的排列是有序號(hào)的,元素相同但排列不同的列表屬于不同的列表。
- 列表索引是從
0
開始的,我們可以通過下標(biāo)索引的方式來訪問列表中的值。- 列表中可以存放不同類型的元素(整數(shù),浮點(diǎn)數(shù),字符串等),可以嵌套(列表,字典,集合)
1.2. 常用功能
- 遍歷:
for/while
循環(huán)遍歷列表;- 增加:
append(),extend(),insert()
分別為末尾添加一個(gè)元素,將一個(gè)列表的元素添加到另一個(gè)列表,在指定位置添加元素;- 查找:
in,not in
;- 修改:指定索引修改,如
li[2] = 'a'
;- 刪除:
del[i],pop(),remove()
分別為根據(jù)下標(biāo)刪除,刪除最后一個(gè)元素,根據(jù)元素值刪除;- 排序:
li.sort(reverse=False)
,li = sorted(li, reverse=False)
一個(gè)是對(duì)象,一個(gè)是函數(shù)實(shí)現(xiàn);- 操作:
+
,*
,==
,<
,>
分別用于列表的拼接,重復(fù)次數(shù),判斷是否相等,判斷列表的大小(從第一個(gè)元素開始進(jìn)行逐個(gè)比較,直到找到不相等的)- 嵌套:列表之間可以嵌套,如
[1,2,3,[1,2,[1,2,3]]]
;- 切片:如
li[:3]
,這一部分更詳細(xì)的操作可參考我的另一篇博文:python切片操作
二. 元組
2.1. 使用規(guī)則
??Python
的元組(tuple
)與列表類似,不同之處在于元組的元素不能修改。元組使用小括號(hào),列表使用方括號(hào)。
- 使用圓括號(hào)
()
表示開始和結(jié)束。- 不同元素以逗號(hào)分隔。
- 每個(gè)元素的排列是有序號(hào)的,元素相同但排列不同的元組屬于不同的元組。
- 元組可以使用下標(biāo)索引來訪問元組中的值 。
- 元組不允許修改元組。
- 元組中只有一個(gè)元素的時(shí)候需要在最后加一個(gè)逗號(hào)
(1,)
2.2. 常用功能
??由于元組是不可變類型,因此,列表中擁有的很多功能在元組中并不適用,如增刪查改、排序等需要改動(dòng)元組的時(shí)候都是不行的。
- 遍歷:
for/while
循環(huán);- 計(jì)數(shù):
len()
用于求取元組的個(gè)數(shù);- 切片:
tu[2:]
;- 轉(zhuǎn)換:
tuple(li)
把列表轉(zhuǎn)為元組;- 操作:
+
,*
,==
,<
,>
分別用于列表的拼接,重復(fù)次數(shù),判斷是否相等,判斷列表的大小(從第一個(gè)元素開始進(jìn)行逐個(gè)比較,知道找到不相等的)
三. 字典
??字典是一種存儲(chǔ)數(shù)據(jù)的容器,它和列表一樣,都可以存儲(chǔ)多個(gè)數(shù)據(jù)。每個(gè)元素都是由兩部分組成的,分別是鍵和值。
3.1. 使用規(guī)則
字典使用規(guī)則:
- 使用花括號(hào){}表示開始和結(jié)束,并且每個(gè)元素是以key:value方式成對(duì)出現(xiàn)。
- 不同元素以逗號(hào)分隔。
- 每個(gè)元素的排列是無序的(不支持索引),元素相同但排列不同的字典屬于相同的字典。
- 根據(jù)鍵訪問值。(注意:如果使用的是不存在的鍵,則程序會(huì)報(bào)錯(cuò)。)
- 鍵值唯一,字典不允許重復(fù),如果嘗試在字典中使用重復(fù)的鍵,則只有最后一個(gè)鍵值對(duì)會(huì)保留在字典中,而之前的鍵值對(duì)會(huì)被丟棄。鍵本身必須唯一。
3.2. 常用功能
- 遍歷:
dicts.key()
,dicts.value
,dicts.items()
分別表示遍歷鍵、值、元組(鍵值對(duì)一個(gè)整體,可以拆開進(jìn)行鍵值對(duì)遍歷);- 增加:直接
dicts['num'] = 110
或者new_dict = {"num": 110}, dicts.update(new_dict)
- 刪除:
del dicts['a']/del dicts
,dicts.pop('a')
,clear()
分別表示刪除元素/整個(gè)字典(刪除整個(gè)字典后字典不就存在了)、刪除元素并返回value
值,清空字典;- 查找:使用鍵訪問
dicts['a']
,如果鍵不存在會(huì)報(bào)錯(cuò)。不確定鍵是否存在可以使用get()
方法,num = dicts.get('num')
。也可以使用in
方法;- 更改:直接修改鍵對(duì)應(yīng)的值,
dicts['a'] = 'xiaoming'
;- 長(zhǎng)度:獲取字典元素的個(gè)數(shù),
len()
;- 鍵:
dicts.keys()
;- 值:
dicts.values()
;
對(duì)字典的遍歷演示一下:
if __name__ == "__main__":
dicts = {'num': 110, 'name': 'xiaoming'}
print("key遍歷:")
for key in dicts.keys():
print(key)
print("value遍歷:")
for value in dicts.values():
print(value)
print("元素遍歷:")
for item in dicts.items():
print(item)
print("鍵值對(duì)遍歷:")
for key, value in dicts.items():
print(key, value)
# 遍歷字典默認(rèn)返回鍵
print("默認(rèn)遍歷返回鍵:")
for key in dicts:
print(key)
輸出:
key遍歷:
num
name
value遍歷:
110
xiaoming
元素遍歷:
('num', 110)
('name', 'xiaoming')
鍵值對(duì)遍歷:
num 110
name xiaoming
默認(rèn)遍歷返回鍵:
num
name
四. 集合
4.1. 使用規(guī)則
- 使用花括號(hào)
{}
表示開始和結(jié)束,并且每個(gè)元素是以單個(gè)元素方式出現(xiàn)。- 不同元素以逗號(hào)分隔。
- 每個(gè)元素的排列是無序的(不支持索引),元素相同但排列不同的集合屬于相同的集合。
- 集合中若有重復(fù)元素,會(huì)自動(dòng)刪除重復(fù)值,不會(huì)報(bào)錯(cuò)。
4.2. 常用功能
??集合中的元素是唯一的,因此集合不支持索引訪問、切片、排序,修改等操作,并且集合的元素必須是不可變類型(整數(shù),字符串,元組等),不能是可變類型(列表,字典等)。可變(Mutable
)類型是指在創(chuàng)建后可以修改其值或內(nèi)容的數(shù)據(jù)類型,而不可變(Immutable
)類型是指在創(chuàng)建后不可修改其值或內(nèi)容的數(shù)據(jù)類型,修改后地址會(huì)變化。簡(jiǎn)單理解可變不可變即修改后地址是否變化。
- 遍歷:
for/while
循環(huán);- 增加:
my_set.add(6)
;- 刪除:
remove()
,discard()
,clear()
都是刪除,第一個(gè)刪除沒有的元素會(huì)報(bào)錯(cuò),第二個(gè)刪除沒有的元素不會(huì)報(bào)錯(cuò),第三個(gè)是清空集合;- 查找:
in
;- 長(zhǎng)度:
len()
;- 集合:
|
,&
,-
,^
分別為并集、交集、差集、交叉補(bǔ)集。
五. 迭代器、生成器、可迭代對(duì)象
5.1. 迭代器
迭代器類型的定義:
- 當(dāng)類中定義了
__next__
和__iter__
兩個(gè)方法__iter__
方法需要返回對(duì)象本身,即:self
__next__
方法,返回下一個(gè)數(shù)據(jù),如果沒有數(shù)據(jù)了,則需要拋出一個(gè)stopIteration
的異常。
??迭代器就是實(shí)現(xiàn)了__next__
和 __iter__
方法(實(shí)際使用的時(shí)候一般是缺一不可,但是python也規(guī)定了可以省略__iter__
,是不是感覺很扯淡,自己規(guī)定要兩個(gè)都寫,有時(shí)候又可以省略,省略__iter__
時(shí)不能通過for循環(huán)遍歷迭代器)的對(duì)象,就叫迭代器。其中 __iter__
方法返回迭代器自身,__next__
方法不斷返回迭代器中的下一個(gè)值,直到容器中沒有更多的元素時(shí)則拋出Stoplteration
異常,以終止迭代。迭代器沒有長(zhǎng)度,不可以用len
來獲取長(zhǎng)度,沒有len
屬性。迭代到最后將會(huì)拋出異常,因此不能重復(fù)迭代。看一下怎么自己創(chuàng)建迭代器:
# 創(chuàng)建迭代器類型:
class IT:
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration()
return self.counter
# 實(shí)例化一個(gè)迭代器對(duì)象
obj1 = IT()
# 返回1
v1 = obj1.__next__()
# 返回2
v2 = obj1.__next__()
# 會(huì)拋出異常
# v3 = obj1.__next__()
obj2 = IT()
# 也可以直接通過內(nèi)置函數(shù)next執(zhí)行
a1 = next(obj2)
a2 = next(obj2)
# 拋出異常
# a3 = next(obj1)
obj3 = IT()
# 首先會(huì)執(zhí)行迭代器對(duì)象的__iter__方法并獲取返回值,然后一直反復(fù)的執(zhí)行next方法,每次執(zhí)行的結(jié)果都會(huì)賦值為item.
for i in obj3:
print(i)
輸出:
1
2
5.2. 生成器
??生成器其實(shí)是一種特殊的迭代器,不過這種迭代器更加優(yōu)雅。它不需要再像上面的類一樣寫__iter()__
和 __next__
方法了,只需要一個(gè)yiled
關(guān)鍵字。也就是說,如果一個(gè)函數(shù)包含yield
關(guān)鍵字( 不管有多少個(gè)yield
),這個(gè)函數(shù)就會(huì)變?yōu)橐粋€(gè)生成器。yield
有什么作用?
- 程序每次在代碼中遇到
yield
關(guān)鍵字后,會(huì)返回結(jié)果- 保留當(dāng)前函數(shù)的運(yùn)行狀態(tài),等待下一次調(diào)用,下次調(diào)用時(shí)從上一次返回
vield
的語(yǔ)句處開始執(zhí)行后面的語(yǔ)句。
# 創(chuàng)建生成器函數(shù),定義一個(gè)函數(shù),只要這個(gè)函數(shù)中出現(xiàn)了yield就是生成器。
def fun():
yield 1
yield 2
yield 3
#
for i in obj1:
print(i)
輸出:
1
2
3
??生成器就是一種特殊的迭代器。yield
可以理解成return
,一個(gè)yield
執(zhí)行完之后,程序就停止到這里,下次在此進(jìn)來的時(shí)候從停止地方來時(shí)執(zhí)行,因此上面的程序可以直接輸出1,2,3
。關(guān)于yield
這個(gè)函數(shù)用法不理解的小伙伴可以跳轉(zhuǎn)到這位大神寫的博文學(xué)一下:python中yield的用法詳解——最簡(jiǎn)單,最清晰的解釋。關(guān)于yield
更高級(jí)的用法可以移步到這個(gè)視頻:Python開發(fā)編程高級(jí)進(jìn)階教程,線程通信/裝飾器/迭代器/異步IO/魔術(shù)方法/反射。
send
方法的作用:
- 像
next
方法一樣去調(diào)用生成器(調(diào)用生成器有兩個(gè)方法:next
方法和send
方法)send
方法在調(diào)用生成器時(shí),可以同時(shí)給生成器傳遞數(shù)據(jù)到生成器內(nèi)部
預(yù)激活生成器有兩種方法:
- 直接調(diào)用
next
方法來激活生成器- 調(diào)用
send(None)
方法來激活生成器
5.3. 可迭代對(duì)象
??從實(shí)現(xiàn)上看,一個(gè)可迭代對(duì)象要么有一個(gè)__iter__
這個(gè)方法 ,要么有是一個(gè)sequence有__getitem__
這個(gè)方法,這兩者都是為了可以在iter()
這個(gè)函數(shù)的作用下返回一個(gè)迭代器,而一個(gè)迭代器必須有__next__
這個(gè)方法,__next__
保證了他在被next()作用的時(shí)候可以返回下一個(gè)可迭代對(duì)象里面的值。
??這里解釋一個(gè)疑惑,如果一個(gè)對(duì)象是可迭代對(duì)象,那么這個(gè)對(duì)象可以被for循環(huán),因?yàn)閒or循環(huán)的內(nèi)部先執(zhí)行obj.__iter__
方法,他返回的是一個(gè)迭代器對(duì)象,我們知道迭代器對(duì)象是可以執(zhí)行obj.__next__
去取值,那么在for循環(huán)的內(nèi)部是不是就基于這個(gè)迭代器對(duì)象調(diào)用它的__next__
是可以幫助我們逐一去取值。這里就出現(xiàn)一個(gè)疑惑了,那么for循環(huán)后面為什么跟一個(gè)迭代器也可以呢?因?yàn)樗绻苯尤パh(huán)迭代器對(duì)象,那迭代器對(duì)象的__iter__
是不是返回的是他自己還是一個(gè)迭代器對(duì)象對(duì)吧,然后再調(diào)用__next__
方法,所以兩者是說得通的,沒毛病。
在python
中可以通過iter()
方法獲取可迭代對(duì)象返回的迭代器,然后使用next()
函數(shù)逐個(gè)獲取其中的元素。當(dāng)?shù)骱谋M時(shí),再次調(diào)用next()函數(shù)會(huì)引發(fā)StopIteration
異常。
自己創(chuàng)建一個(gè)可迭代對(duì)象:
# 如果一個(gè)類中有__iter__方法且返回一個(gè)迭代器對(duì)象 ; 則我們稱以這個(gè)類創(chuàng)建的對(duì)象為可迭代對(duì)象。
class Foo:
def __iter__(self):
return 迭代器對(duì)象/生成器對(duì)象
# 可迭代對(duì)象是可以使用for來進(jìn)行循環(huán)的,在循環(huán)的內(nèi)部其實(shí)是先執(zhí)行__iter__方法,
# 獲取其迭代器對(duì)象,然后再在內(nèi)部執(zhí)行這個(gè)迭代器對(duì)象的next功能,逐步取值。
obj = Foo()
for i in obj:
pass
先看個(gè)通過__getitem__
創(chuàng)建的簡(jiǎn)單例子:
class Employee:
def __init__(self, employee):
self.employee = employee
# item是解釋器幫我們維護(hù)索引值,在for循環(huán)的時(shí)候自動(dòng)從0開始計(jì)數(shù)。
def __getitem__(self, item):
return self.employee[item]
emp = Employee(["zhangsan", "lisi", "wangwu"])
for i in emp:
print(i)
再看個(gè)例子:
class IT:
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration()
return self.counter
# 如果類中有__iter__方法并且返回一個(gè)迭代器對(duì)象,這個(gè)創(chuàng)建的對(duì)象就成為可迭代對(duì)象。
class Foo:
def __iter__(self):
return IT()
# 循環(huán)可迭代對(duì)象時(shí),內(nèi)部先執(zhí)行obj.__iter__并獲取迭代器對(duì)象,然后在for循環(huán)內(nèi)部不斷地執(zhí)行迭代器對(duì)象的next方法
# (區(qū)別一下迭代器是先調(diào)用__iter__方法返回自己本身,然后在調(diào)用next方法,這里是內(nèi)部先執(zhí)行iter方法返回迭代器對(duì)象,然后迭代器對(duì)象去調(diào)用next方法。)
obj = Foo()
for i in obj:
print(i)
輸出:
1
2
基于上面的理解,我們來自己創(chuàng)建一個(gè)基于迭代器的range
方法:
class ItRange:
def __init__(self, num):
self.num = num
self.counter = -1
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == self.num:
raise StopIteration()
return self.counter
class my_range:
def __init__(self, max_num):
self.max_num = max_num
def __iter__(self):
return ItRange(self.max_num)
for i in my_range(5):
print(i)
輸出:
0
1
2
3
4
再來看一個(gè)基于生成器的自定義range
方法:
class my_range:
def __init__(self, max_num):
self.max_num = max_num
def __iter__(self):
counter = 0
while counter <self.max_num:
yield counter
counter += 1
for i in my_range(5):
print(i)
輸出:
0
1
2
3
4
總結(jié):
- 迭代器:類,實(shí)現(xiàn)了
__iter__
和__next__
接口的類。- 生成器:函數(shù),通過
yield
遍歷元素。- 可迭代對(duì)象:一般為數(shù)據(jù)容器,且保留 迭代接口
__iter__
。
__iter__
方法是留給程序獲得迭代對(duì)象iter()
;- 獲得迭代對(duì)象后,通過
__next__
或next()
遍歷元素。
迭代器一定是可迭代對(duì)象,可迭代對(duì)象不一定是迭代器
為什么有了可迭代對(duì)象還要有迭代器?
答:
雖然可迭代對(duì)象可以通過iter()函數(shù)轉(zhuǎn)換為迭代器,但迭代器的設(shè)計(jì)目的是為了提供一種惰性生成元素的方式。迭代器在每次請(qǐng)求元素時(shí)才會(huì)計(jì)算或生成,而不是一次性將所有元素都存儲(chǔ)在內(nèi)存中。節(jié)約了空間。
舉兩個(gè)例子:
# 創(chuàng)建一個(gè)包含大量元素的列表
large_list = [i for i in range(1000000)]
# 使用for循環(huán)遍歷大型列表
for item in large_list:
process_item(item)
??在上述代碼中,我們直接使用for
循環(huán)遍歷大型列表large_list
。這樣做會(huì)一次性將整個(gè)列表加載到內(nèi)存中,然后逐個(gè)獲取列表中的元素進(jìn)行處理。這種方法會(huì)在處理大型列表時(shí)占用大量的內(nèi)存,特別是當(dāng)列表非常龐大時(shí)。如果列表太大而無法一次性放入內(nèi)存中,可能會(huì)導(dǎo)致內(nèi)存溢出的問題。
看下使用迭代器的方法:
class LargeListIterator:
def __init__(self, large_list):
self.large_list = large_list
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.large_list):
raise StopIteration
value = self.large_list[self.index]
self.index += 1
return value
# 創(chuàng)建一個(gè)包含大量元素的列表
large_list = [i for i in range(1000000)]
# 使用迭代器逐個(gè)獲取列表中的元素
iterator = LargeListIterator(large_list)
for item in iterator:
process_item(item)
??過創(chuàng)建
LargeListIterator
的實(shí)例并將大型列表傳遞給它,我們可以在for
循環(huán)中使用迭代器逐個(gè)處理列表中的元素,而不需要一次性將整個(gè)列表加載到內(nèi)存中。這種方式可以有效地處理大型列表,節(jié)省內(nèi)存并提高性能。迭代器會(huì)在需要時(shí)按需生成列表元素,而不是一次性生成整個(gè)列表。
七. zip函數(shù)
zip()
函數(shù)用于將可迭代的對(duì)象作為參數(shù),將對(duì)象中對(duì)應(yīng)的元素打包成一個(gè)個(gè)元組,即返回一個(gè)zip迭代器(python2是返回一個(gè)可迭代的zip對(duì)象)。
- 如果各個(gè)迭代器的元素個(gè)數(shù)不一致,則返回列表長(zhǎng)度與最短的對(duì)象相同
- 利用
*
號(hào)操作符,可以將元組解壓為列表。
python
中常見的可迭代對(duì)象:列表,元組,字符串,字典,集合,文件對(duì)象,生成器等。可以通過下面的方法進(jìn)行判斷:
from collections.abc import Iterator, Iterable
l1 = [1, 2, 3, 4, 5]
print(isinstance(l1, Iterator))
print(isinstance(l1.__iter__(), Iterator))
L2 = [1, 2, 3, 4, 5]
# Iterable無法判斷一個(gè)對(duì)象是否是可迭代對(duì)象,需要配合Iterator進(jìn)行判斷(不是迭代器,但是是一個(gè)Iterable表明是一個(gè)可迭代對(duì)象)
print(isinstance(l1, Iterable))
print(isinstance(l1.__iter__(), Iterable))
輸出:
False
True
True
True
來看下zip
函數(shù)怎么打包的:
list1 = [1, 2, 3, 4, 5]
list2 = ["hello", "good", "nice", "haha"]
# 集合是一個(gè)無序,無重復(fù)的可迭代對(duì)象,0=False,實(shí)際上內(nèi)部按照一定邏輯對(duì)集合已經(jīng)排序好了
set3 = {True, False, None, 0}
print(set3)
print('*' * 60)
zip_tup = zip(list1, list2, set3) # 打包
for i in zip_tup:
print(i)
print('*' * 60)
zip_tup = zip(list1, list2, set3)
print(next(zip_tup))
print(next(zip_tup))
print(next(zip_tup))
print('*' * 60)
print(zip_tup)
print('*' * 60)
zip_tup = zip(list1, list2, set3)
print(list(zip_tup)) # 可以將包轉(zhuǎn)化為列表,查看包中的內(nèi)容
輸出:
{False, True, None}
************************************************************
(1, 'hello', False)
(2, 'good', True)
(3, 'nice', None)
************************************************************
(1, 'hello', False)
(2, 'good', True)
(3, 'nice', None)
************************************************************
<zip object at 0x0000027E1E353A48>
************************************************************
[(1, 'hello', False), (2, 'good', True), (3, 'nice', None)]
再來看下怎么解包:
元組通過*
進(jìn)行解包
"""
拆包
"""
list1 = [1, 2, 3, 4, 5]
list2 = ["hello", "good", "nice", "haha"]
# 集合是一個(gè)無序,無重復(fù)的可迭代對(duì)象,0=False,實(shí)際上內(nèi)部按照一定邏輯對(duì)集合已經(jīng)排序好了
set3 = {True, False, None, 0}
zip_tup = zip(list1, list2, set3) # 打包
li_zip = list(zip_tup)
print(li_zip)
print('*' * 60)
zip_tup = zip(list1, list2, set3) # 打包
for item in zip(*zip_tup):
print(item)
輸出:
[(1, 'hello', False), (2, 'good', True), (3, 'nice', None)]
************************************************************
(1, 2, 3)
('hello', 'good', 'nice')
(False, True, None)
字典通過**
解包,看一個(gè)函數(shù)傳參的經(jīng)典例子:
person = {"name": "Alice", "age": 25, "city": "New York"}
tu = (1, 2, 3, 4)
def fun(*args, **kwargs):
print(args)
print(kwargs)
fun(tu, person)
fun(*tu, **person)
# 不使用拆包需要手動(dòng)拆包
fun(1, 2, 3, 4, name="Alice", age=25, city="New York")
這里提個(gè)問題:
??直接定義一個(gè)l1=[1,2,3,4,5]
,l2=[1,2,3,4,5]
打印l1
,l2
輸出的就是列表的內(nèi)容,l1
,l2
也是一個(gè)可迭代對(duì)象,可以直接打印內(nèi)容,為什么zip(l1,l2)
直接打印就不能直接輸出元組呢?他的返回不也是一個(gè)可迭代對(duì)象嗎?
答:
- 列表是一種可迭代對(duì)象,可以直接打印其內(nèi)容。列表對(duì)象內(nèi)部實(shí)現(xiàn)了
__iter__()
方法,使其可以被迭代。當(dāng)你直接打印一個(gè)列表時(shí),Python
會(huì)調(diào)用列表的__str__()
方法,返回列表的字符串表示形式,其中包含了列表的內(nèi)容。zip()
函數(shù)返回一個(gè)迭代器,實(shí)際上是一個(gè)迭代器,用于生成元組序列。當(dāng)你直接打印zip()
返回的可迭代對(duì)象時(shí),它會(huì)顯示為一個(gè)類的標(biāo)識(shí)符,而不是直接輸出元組的內(nèi)容。這是因?yàn)樵?Python
中,打印一個(gè)對(duì)象時(shí),默認(rèn)會(huì)調(diào)用對(duì)象的__repr__()
方法來顯示其表示形式。
加深一下印象,我們?cè)賮砜磦€(gè)例子:
# 將每個(gè)元組的元素作為參數(shù)傳遞給函數(shù)
def print_values(a, b):
print("Value of a:", a)
print("Value of b:", b)
# 使用解包操作符 * 將元組的元素作為參數(shù)傳遞給函數(shù)
for tuple_values in zip(l1, l2):
print_values(*tuple_values)
print("-" * 10)
# 在打印語(yǔ)句中輸出多個(gè)值
for tuple_values in zip(l1, l2):
print(*tuple_values)
Value of a: 1
Value of b: 2
----------
Value of a: 2
Value of b: 3
----------
Value of a: 3
Value of b: 4
----------
Value of a: 4
Value of b: 5
----------
1 2
2 3
3 4
4 5
八. enumerate函數(shù)
??這個(gè)函數(shù)比較簡(jiǎn)單,enumerate(iteration, start)
函數(shù)默認(rèn)包含兩個(gè)參數(shù),其中iteration
參數(shù)為需要遍歷的參數(shù),比如字典、列表、元組等,start參數(shù)為開始的參數(shù),默認(rèn)為0
(不寫start那就是從0
開始)。enumerate
函數(shù)有兩個(gè)返回值,第一個(gè)返回值為從start
參數(shù)開始的數(shù),第二個(gè)參數(shù)為iteration
參數(shù)中的值。
來看個(gè)例子:
names = ["Alice", "Bob", "Carl"]
for index, value in enumerate(names):
print(f'{index}: {value}')
0: Alice
1: Bob
2: Carl
從結(jié)果上看,他返回了列表中的所有元素并且加上了索引號(hào),默認(rèn)從0
開始。
九. 打包
上面簡(jiǎn)要介紹了*
的用法,下面再來詳細(xì)介紹下打包和解包。
??在函數(shù)定義的時(shí)候,如果變量的前面加上*
則表示收集所有位置參數(shù)到一個(gè)新的元組,并將整個(gè)元組賦值為新的變量args
,如果變量前面加上的是**
,則表示收集關(guān)鍵字參數(shù)到一個(gè)新的字典,并將字典賦值給變量kargs
。下面分別看一個(gè)例子。
*
在函數(shù)定義的時(shí)候使用:
def f(*args): # * 在函數(shù)定義中使用
print(args)
f()
f(1)
f(1, 2, 3, 4)
輸出:
()
(1,)
(1, 2, 3, 4)
**
在函數(shù)定義的時(shí)候使用:
def f(**kwargs): # ** 在函數(shù)定義中使用
print(kwargs)
f()
f(a=1, b=2)
輸出:
{}
{'a': 1, 'b': 2}
十. 解包
??解包參數(shù)和打包參數(shù)一樣,也是*
和**
,只不過這時(shí)候*
和**
不是用在函數(shù)的定義的時(shí)候了,而是用在了函數(shù)的調(diào)用階段,只有在調(diào)用階段這兩個(gè)參數(shù)才表示解包。在函數(shù)調(diào)用中,*
能夠?qū)⒃M或列表解包成不同的參數(shù)(打包的時(shí)候是打包成元祖,解包可以解包元祖和列表,集合)。在函數(shù)調(diào)用中,**
會(huì)以鍵/值的形式解包一個(gè)字典,使其成為一個(gè)獨(dú)立的關(guān)鍵字參數(shù)。下面看幾個(gè)例子。*
在函數(shù)調(diào)用的時(shí)候:
def func(a, b, c, d):
print(a, b, c, d)
args = (1, 2, 3, 4)
func(*args) # * 在函數(shù)調(diào)用中使用
args = [1, 2, 3, 4]
func(*args)
args = {1, 2, 3, 4}
func(*args)
輸出:
1 2 3 4
1 2 3 4
1 2 3 4
**
在函數(shù)調(diào)用的時(shí)候:
def func(a, b, c, d):
print(a, b, c, d)
kwargs = {"a": 1, "b": 2, "c": 3, "d": 4}
func(**kwargs) # ** 在函數(shù)調(diào)用中使用
輸出:
1 2 3 4
總結(jié):
在函數(shù)定義時(shí),*
和**
表示打包,在函數(shù)體內(nèi)部,*
和**
表示的卻是解包??磦€(gè)例子:
def foo(*args, **kwargs):
print(args) # 未解包參數(shù)
print(*args) # 解包參數(shù)
v = (1, 2, 4)
d = {'a': 1, 'b': 12}
foo(v, d)
輸出:
((1, 2, 4), {'a': 1, 'b': 12})
(1, 2, 4) {'a': 1, 'b': 12}
可以看到,在一開始,v,d作為整體被打包成了一個(gè)元祖,然后在解包回原來的形式。
在看一個(gè)例子:
def foo(*args, **kwargs):
print(args) # 未解包參數(shù)
print(*args) # 解包參數(shù)
print(kwargs) # 未解包參數(shù)
v = (1, 2, 4)
d = {'a': 1, 'b': 12}
foo(v, d, a=1, b=-2)
輸出:文章來源:http://www.zghlxwxcb.cn/news/detail-466533.html
((1, 2, 4), {'a': 1, 'b': 12})
(1, 2, 4) {'a': 1, 'b': 12}
{'a': 1, 'b': -2}
此時(shí),v
,d
由*args打
包,然后解包,a=1
,b=-2
(關(guān)鍵字)由**kwargs
打包。文章來源地址http://www.zghlxwxcb.cn/news/detail-466533.html
到了這里,關(guān)于一文詳解列表,元組,字典,集合,生成器,迭代器,可迭代對(duì)象,zip,enumerate的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!