您好,登錄后才能下訂單哦!
?
list comprehension,列表解析:
語法:
[返回值 for 元素 in 可迭代對象 if 條件]
?
注:
列表解析沒有elif,如果有多個條件可用多個if或配合or或and使用;
?
列表解析是語法糖:
編譯器會優化,不會因為簡寫而影響效率,反而因優化提高了效率,不僅字節碼更少,而且減少了棧針;
減少程序員工作量,減少出錯;
簡化了代碼,可讀性增強;
?
例:
生成一個列表,元素0-9,對每一個元素自增1后求平方,返回新列表;
[(i+1)**2 for i in range(0,10)]
?
例:
獲取10以內的偶數,比較執行效率;
方一:
[i for i in range(0,10) if i % 2 == 0]
方二:
even = []
for i in range(10):
??? if not i % 2:?? #常用not這種寫法,同if i % 2 == 0:
??????? even.append(i)
print(even)
?
例:
[0 for _ in range(10)]
[[0] for _ in range(10)]
?
習題:
1、有這樣的賦值語句:newlist=[print(i) for i in range(10)],newlist的元素打印出的是什么?
In [3]: newlist=[print(i) for i in range(5)]
0
1
2
3
4
In [4]: newlist
Out[4]: [None, None, None, None, None]?? #print(i)是表達式的結果或函數計算的結果,print(i)輸出到屏幕了,該列表解析沒有返回值,即最后生成指定個數的None
?
2、獲取20以內的偶數?如果是3的倍數也打印?
In [6]: [i for i in range(20) if not i%2]
Out[6]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
In [7]: [i for i in range(20) if not i%2 or not i%3]?? #list comprehension沒有elif,多個條件用多個if或配合or,and使用
Out[7]: [0, 2, 3, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18]
?
3、獲取20以內既能被2整除又能被3整除的數?
方一:
In [7]: [i for i in range(20) if not i%2 and not i%3]
Out[7]: [0, 6, 12, 18]
方二:
In [8]: [i for i in range(20) if not i%2 if not i%3]
Out[8]: [0, 6, 12, 18]
?
列表解析進階:
[expr for item in iterable if cond1 if cond2]
等價于
ret=[]
for item in iterable:
???????? if cond1:
?????????????????? if cond2:
??????????????????????????? ret.append(expr)
?
[expr for i in iterable1 for j in iterable2]
等價于
ret=[]
for i in iterable1:
???????? for j in iterable2:
?????????????????? ret.append(expr)
?
例:
In [10]: [(i,j) for i in 'abc' for j in range(3)]
Out[10]:
[('a', 0),
?('a', 1),
?('a', 2),
?('b', 0),
?('b', 1),
?('b', 2),
?('c', 0),
?('c', 1),
?('c', 2)]
In [11]: [[i,j] for i in 'abc' for j in range(3)]
Out[11]:
[['a', 0],
?['a', 1],
?['a', 2],
?['b', 0],
?['b', 1],
?['b', 2],
?['c', 0],
?['c', 1],
?['c', 2]]
In [12]: [{i:j} for i in 'abc' for j in range(3)]
Out[12]:
[{'a': 0},
?{'a': 1},
?{'a': 2},
?{'b': 0},
?{'b': 1},
?{'b': 2},
?{'c': 0},
?{'c': 1},
?{'c': 2}]
?
習題:
(1)如下語句的輸出?
In [17]: [(i,j) for i in range(7) for j in range(20,25) if i>4 if j>23]
Out[17]: [(5, 24), (6, 24)]
In [18]: [(i,j) for i in range(7) if i>4 for j in range(20,25) if j>23]
Out[18]: [(5, 24), (6, 24)]
In [19]: [(i,j) for i in range(7) for j in range(20,25) if i>4 and j>23]?? #常用此種
Out[19]: [(5, 24), (6, 24)]
?
(2)返回1到10平方的列表?
In [20]: [i**2 for i in range(1,11)]
Out[20]: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
?
(3)lst=[1,4,9,16,2,5,10,15],生成一個新列表,要求新列表元素是lst相鄰兩項之和?
lst = [1,4,9,16,2,5,10,15]
[lst[i]+lst[i+1] for i in range(len(lst)-1)]
?
(4)打印九九乘法表?
[print('{}*{}={:<3}{}'.format(j,i,i*j,'\n' if i==j else ''),end='') for i in range(1,10) for j in range(1,i+1)]
?
(5)'0001.abadicddus'是ID格式,要求ID格式以點號分割,左邊是4位從1開始的整數,右邊是10位隨機小寫英文字母,請依次生成前100個ID的列表?
方一:
import random
['{:04}.{}'.format(i,''.join([chr(random.randint(97,122)) for _ in range(10)])) for i in range(1,101)]
方二:
import random
import string
['{:04}.{}'.format(i,''.join([random.choice(string.ascii_lowercase) for _ in range(10)])) for i in range(1,101)]
方三:
import random
['{:04}.{}'.format(i,''.join([random.choice(bytes(range(97,123)).decode()) for _ in range(10)])) for i in range(1,101)]
?
注:
ascii,american standard code for information interchange,美國信息交換標準代碼;
小寫a-z對應ascii碼的97-122;
ascii碼表的0-127常用,0-9,\t,\n,\r,space對應的ascii;
chr(),將ascii碼對應的數字轉為字符;
0-31,127,33個控制字符,或通信專用字符;
32-126,95個字符;
32,空格;
48-57,0-9數字;
65-90,26個大寫英文字母;
97-122,26個小寫英文字母;
8,退格;
9,制表;
10,換行;
13,回車;
?
?
?
generator expression,生成器表達式:
語法:
(返回值 for 元素 in 可迭代對象 if 條件)
列表解析的[]換為()即可;
返回一個生成器;
?
和list comprehension區別:
generator expression是按需計算,或稱惰性求值(延遲計算,python思想),需要的時候才計算值,不需要的時候給個對象(可理解為中間狀態,是一種可迭代對象);
list comprehension是立即返回值;
預計算和延遲計算,都有應用場景;
?
生成器:
iterable,可迭代對象;
iterator,迭代器;
iterable不一定是iterator,iterator一定是iterable;
next(),用next()方法測試是否是iterator;
在迭代時最好用for控制,如果直接用next()要控制好邊界,否則拋異常;
迭代完后,不能回頭;
?
生成器總結:
延遲計算;
返回迭代器,可以迭代;
從前到后走完一遍后,不能回頭;
?
列表解析總結:
立即計算;
返回的不是迭代器,返回可迭代對象列表;
從前到后走完一遍后,可重新回頭迭代;
?
例:
In [1]: [i for i in range(5)]
Out[1]: [0, 1, 2, 3, 4]
In [2]: (i for i in range(5))
Out[2]: <generator object <genexpr> at 0x7fc6440cc9e8>
In [3]: for x in (i for i in range(5)):
?? ...:???? print(x)
?? ...:????
0
1
2
3
4
In [11]: g=('{:04}'.format(i) for i in range(1,4))
In [12]: next(g)??
Out[12]: '0001'
In [13]: next(g)
Out[13]: '0002'
In [14]: next(g)
Out[14]: '0003'
In [15]: next(g)
---------------------------------------------------------------------------
StopIteration???????????????????????????? Traceback (most recent call last)
<ipython-input-15-e734f8aca5ac> in <module>()
----> 1 next(g)
StopIteration:
In [16]: g=('{:04}'.format(i) for i in range(1,4))?? #iterator最好用for控制
In [17]: for i in g:
??? ...:???? print(i)
??? ...:????
0001
0002
0003
In [23]: lc=['{:04}'.format(i) for i in range(5)]
In [25]: for x in lc:
??? ...:???? print(x)
??? ...: print('############')
??? ...: for x in lc:
??? ...:???? print(x)
??? ...:????
0000
0001
0002
0003
0004
############
0000
0001
0002
0003
0004
?
?
習題:
it=(print('{}'.format(i+1)) for i in range(2))
first=next(it)
second=next(it)
val=first+second
val的值是什么??? #報錯,print()語句是輸出到控制臺,該生成器返回值為None
val=first+second語句之后,能否再次next(it)??? #不能
In [18]: it=(print('{}'.format(i+1)) for i in range(2))
In [19]: type(it)
Out[19]: generator
In [20]: first=next(it)
1
In [21]: second=next(it)
2
In [22]: val=first+second
---------------------------------------------------------------------------
TypeError?? ??????????????????????????????Traceback (most recent call last)
<ipython-input-22-663c3b91df51> in <module>()
----> 1 val=first+second
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'
?
生成器表達式和列表解析式的對比:
計算方式,生成器表達式延遲計算,列表解析式立即計算;
內存占用,單從返回值本身來說,生成器表達式省內存,列表解析式返回新的列表(構造出新的列表,需占用內存);生成器沒有數據,內存占用極少,但使用時,雖然一個個返回數據,但合起來占用的內存也差不多;
計算速度,單從計算時間看,生成器表達式耗時非常短,列表解析式耗時時間長;但是生成器本身并沒有返回任何值,只返回了一個生成器對象;列表解析式構造并返回了一個新的列表;
?
?
集合解析式:
語法:
{返回值 for 元素 in 可迭代對象 if 條件}
{}
立即返回一個集合;
?
例:
In [26]: {(x,x+1) for x in range(5)}
Out[26]: {(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)}
In [27]: {[x] for x in range(5)}
---------------------------------------------------------------------------
TypeError???????????????????????????????? Traceback (most recent call last)
<ipython-input-27-a39ffa943c7e> in <module>()
----> 1 {[x] for x in range(5)}
<ipython-input-27-a39ffa943c7e> in <setcomp>(.0)
----> 1 {[x] for x in range(5)}
TypeError: unhashable type: 'list'
?
字典解析式:
語法:
{返回值 for 元素 in 可迭代對象 if 條件}
{},用key:value形式;
立即返回一個字典;
?
例:
In [28]: {x:(x,x+1) for x in range(5)}
Out[28]: {0: (0, 1), 1: (1, 2), 2: (2, 3), 3: (3, 4), 4: (4, 5)}
In [29]: {x:[x,x+1] for x in range(5)}
Out[29]: {0: [0, 1], 1: [1, 2], 2: [2, 3], 3: [3, 4], 4: [4, 5]}
In [30]: {[x]:[x,x+1] for x in range(5)}
---------------------------------------------------------------------------
TypeError???????????????????????????????? Traceback (most recent call last)
<ipython-input-30-32f94dcaf39f> in <module>()
----> 1 {[x]:[x,x+1] for x in range(5)}
<ipython-input-30-32f94dcaf39f> in <dictcomp>(.0)
----> 1 {[x]:[x,x+1] for x in range(5)}
TypeError: unhashable type: 'list'
In [31]: {(x,):[x,x+1] for x in range(5)}
Out[31]: {(0,): [0, 1], (1,): [1, 2], (2,): [2, 3], (3,): [3, 4], (4,): [4, 5]}
In [32]: {chr(0x41+x):x**2 for x in range(5)}
Out[32]: {'A': 0, 'B': 1, 'C': 4, 'D': 9, 'E': 16}
In [33]: {str(x):y for x in range(3) for y in range(4)}?? #等價于如下
Out[33]: {'0': 3, '1': 3, '2': 3}
In [34]: ret={}
In [36]: for i in range(3):
??? ...:???? for j in range(4):
??? ...: ????????ret[str(i)]=j
??? ...:????????
??? ...:????????
In [37]: ret
Out[37]: {'0': 3, '1': 3, '2': 3}
?
python2引入列表解析式;
python3引入生成器表達式;
python3引入集合解析式、字典解析式、并遷移到了2.7;
一般來說,要多應用解析式、簡短、高效;
如果一個解析式非常復雜,難以讀懂,要考慮拆解成for循環;
生成器和迭代器是不同的對象,但都是可迭代對象;
?
iter(iterable),將一個可迭代對象封裝成一個迭代器;
next(iterator),取元素,對一個迭代器取下一個元素,如果元素全部取完,再next()會拋StopIteration異常;
?
可迭代對象:
能夠通過迭代一次次返回不同元素的對象,所謂相同不是指值是否相同,而是元素在容器中是否是同一個,如list中值可重復;
可以迭代,但是未必有序,未必可索引;
可迭代對象有,list,tuple,string,bytes,bytearray,range,set,dict,iterator等;
可用成員運算符in,not in,in本質上就是在遍歷對象;
?
迭代器:
特殊的對象,一定是可迭代對象,具備可迭代對象的特征;
通過iter(iterable)把一個可迭代對象封裝成迭代器;
通過next()迭代迭代器對象;
生成器對象,就是迭代器對象;
迭代器不一定是生成器;
?
?
?
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。