列表生成式
列表生成式是 python 內(nèi)置的非常強(qiáng)大的可以用來生成列表的生成式预麸。在學(xué)習(xí)生成器之前先來了解一下列表生成式抢呆,者有利于我們隊(duì)生成器的理解劣光。
列表生成式的語法格式如下
[exp for iter_var in iterable if_exp]
列表生成式的實(shí)際執(zhí)行過程如下:
- 迭代 iterable 中的每個(gè)元素国觉,每次迭代都先判斷 if_exp 表達(dá)式結(jié)果為真,如果為真則進(jìn)行下一步嫡良,如果為假則進(jìn)行下一次迭代;
- 把迭代結(jié)果賦值給 iter_var献酗,然后通過 exp 得到一個(gè)新的計(jì)算值寝受;
- 最后把所有通過 exp 得到的計(jì)算值以一個(gè)新列表的形式返回。
如果迭代得到的元素?zé)o需過濾的話罕偎,if_exp 可以省略很澄。
我們?nèi)绻梢粋€(gè) 1 至 100 的整數(shù)的列表可以使用 list(range(1,101)), 如果要 1 到 100 的整數(shù)的平方我們可以使用循環(huán)來實(shí)現(xiàn)
list = []
for x in range(1, 101):
list.append(x * x)
print(list)
除了使用選好我們還可以使用列表生成式來實(shí)現(xiàn)
list = [x * x for x in range(1, 101)]
print(list)
現(xiàn)在我們需要 1 至 100 中所有偶數(shù)的的平方,我們也可以使用列表生成式來實(shí)現(xiàn)
list = [x * x for x in range(1, 101) if x % 2 == 0]
print(list)
通過使用列表生成式我們可以寫出簡(jiǎn)潔的代碼來快速的初始化列表颜及。
生成器
生成器從名字上來看可以理解為生成數(shù)據(jù)的工具甩苛。生成器按照某種特定的規(guī)則不斷的生成數(shù)據(jù),直到結(jié)束為止俏站。
生成器的語法規(guī)則如下:
(exp for iter_var in iterable if_exp)
從形式上看生成器和列表生成式非常相似讯蒲,生成器僅僅是將列表生成式的方括號(hào)換成了圓括號(hào)。而實(shí)際使用上卻有很大的差別肄扎,列表生成式一次生成一個(gè)列表若列表的元素過多則占用很大的內(nèi)存空間墨林,而生成器一次僅生成一個(gè)元素即節(jié)省了內(nèi)存空間又可以獲取完整的列表內(nèi)容。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
list1 = [x * x for x in range(1, 20) if x % 2 == 0]
list2 = (x * x for x in range(1, 20) if x % 2 == 0)
print(type(list1))
print(type(list2))
print(list1)
print(list2)
for n in list2:
print(n)
for n in list2:
print(n)
以上代碼執(zhí)行結(jié)果如下:
<class 'list'>
<class 'generator'>
[4, 16, 36, 64, 100, 144, 196, 256, 324]
<generator object <genexpr> at 0x101163390>
4
16
36
64
100
144
196
256
324
從以上代碼的執(zhí)行結(jié)果我們可以看出犯祠,使用列表生成式即生成了一個(gè)完整的列表旭等,包含了列表的所有元素;使用生成器產(chǎn)生的是一個(gè)生成器衡载,本身未含有任何元素搔耕,當(dāng)我們使用 for 循環(huán)進(jìn)行迭代時(shí)可以獲取生成器生成的整個(gè)列表的元素,但是生成器僅能迭代一次,迭代完成后將無法再獲取內(nèi)容,這也是迭代器的特性冀泻。
生成器解具有很多用途麦箍,在很多地方替代列表使用是一個(gè)不錯(cuò)的選擇。特別是針對(duì)大量值的時(shí)候咬腕,列表占內(nèi)存較多,生成器的優(yōu)勢(shì)就在于少占內(nèi)存,因此無需將生成器實(shí)例化為一個(gè)列表腊凶,直接對(duì)其進(jìn)行操作,方顯示出其迭代的優(yōu)勢(shì)。
以上列表是比較簡(jiǎn)單的生成器钧萍,可以直接使用列表生成式修改得到褐缠,如果是比較復(fù)雜的生成器則需要使用包含 yield 的函數(shù)來實(shí)現(xiàn)。下面我們通過 yield 函數(shù)來實(shí)現(xiàn)上面的列表(包含 1 至 20 中所有偶數(shù)的平方)风瘦。
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def even_squares(start, end):
for n in range(start, end):
if n % 2 == 0:
yield n * n
list = even_squares(1, 20)
print(type(list))
print(list)
for n in list:
print(n)
以上代碼執(zhí)行結(jié)果如下
<class 'generator'>
<generator object even_squares at 0x10aa38c00>
4
16
36
64
100
144
196
256
324
從以上代碼運(yùn)行結(jié)果可以看出使用 yield 函數(shù)和使用列表生成式的生成器獲取的結(jié)果完全相同队魏。
生成器具有以下特點(diǎn):
- 可以使用類似列表生成式的方式生成,也可以使用 yield 函數(shù)生成万搔。
- 生成器只在使用時(shí)才生成數(shù)據(jù)胡桨,可用來節(jié)省內(nèi)存空間。
- 生成器實(shí)際是一個(gè)特殊的迭代器瞬雹,可以使用 for 循環(huán)進(jìn)行迭代昧谊。
- 只記錄當(dāng)前的位置,只能向前不能向后酗捌,「生成器只能使用一次呢诬,再次使用需重新初始化」。