Python-各种结构解析以及生成器(列表解析,字典解析,集合解析,元组构成的生成器)
1、列表解析:
- 舉例:生成一個列表,元素0-9,對每一個元素自增1后求平方返回新列表。
可以看出,是將一個for循環拉平,放到一個列表中。(不是簡單的拉平!!)
- 語法:
[ 返回值 for 元素 in 可迭代帶對象 if 條件 ]
使用中括號 [] ,內部是for 循環 ,if條件語句可選
返回一個列表
- 列表解析式是一種語法糖:
編譯器會優化,不會因為簡寫而影響效率,反而因優化提高了效率
減少程序員工作量,減少出錯
簡化了代碼,但是可讀性增強
舉例
lst = [i for i in range(21) if not i % 2 if not i % 3] print(lst) # [0, 6, 12, 18] lst = [i for i in range(21) if i % 2 == 0 if i % 3 == 0] print(lst) # [0, 6, 12, 18]lst = [i for i in range(21) if not i % 2 elif not i % 3] print(lst) # 這樣是會拋SyntaxError異常lst = [] for i in range(21):if i % 2 ==0:lst.append(i)elif i % 3 == 0:lst.append(i) print(lst) # [0, 2, 3, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20]首先,結果不滿足,其次,如果有elif 同一層的語句,是不能寫成如上的解析式的。
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' lst = [] for i in range(21):if i % 2 ==0 and i % 3 == 0:lst.append(i) print(lst) # [0, 6, 12, 18]#-------->lst = [ i for i in range(21) if not i % 2 and i % 3 ==0] print(lst) # [0, 6, 12, 18]lst = [ i for i in range(21) if not i % 2 or i % 3 ==0] print(lst) # [0, 2, 3, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20]lst = [i for i in range(21) if i % 2 == 0 if i % 3 == 0] # 在第一個if下執行第二個iflst = [ i for i in range(21) if not i % 2 and i % 3 ==0] # 直接將兩個if 條件合并 # 這兩個是等價的
注:循環條件都是一層一層的,第一層for下,執行第二層for,以此類推。
舉例-陷阱
t1 = [[x,y] for x in 'abced' for y in range(3)] print(t1) # [['a', 0], ['a', 1], ['a', 2], ['b', 0], ['b', 1], ['b', 2], ['c', 0], ['c', 1], ['c', 2], ['e', 0], ['e', 1], ['e', 2], ['d', 0], ['d', 1], ['d', 2]]t2 = [{x,y} for x in 'abced' for y in range(3)] print(t2) # [{0, 'a'}, {1, 'a'}, {2, 'a'}, {0, 'b'}, {1, 'b'}, {2, 'b'}, {0, 'c'}, {1, 'c'}, {2, 'c'}, {0, 'e'}, {1, 'e'}, {2, 'e'}, {0, 'd'}, {1, 'd'}, {2, 'd'}]t2 = [{x:y} for x in 'abced' for y in range(3)]# [{'a': 0}, {'a': 1}, {'a': 2}, {'b': 0}, {'b': 1}, {'b': 2}, {'c': 0}, {'c': 1}, {'c': 2}, {'e': 0}, {'e': 1}, {'e': 2}, {'d': 0}, {'d': 1}, {'d': 2}]分析三種不同順序的結果
t1 = [(i, j) for i in range(7) if i > 4 for j in range(20,25) if j > 23] print(t1) # 相比下面的兩種個,這個效率略有提高,先比較,在進入下一次循環,但是也沒什么事t2 = [(i, j) for i in range(7) for j in range(20,25)if i > 4 if j > 23] print(t2)t3 = [(i, j) for i in range(7) for j in range(20,25)if i > 4 and j > 23] print(t3)# [(5, 24), (6, 24)] # [(5, 24), (6, 24)] # [(5, 24), (6, 24)]- 練習題:
打印九九乘法表
1*1=1 1*2=2 2*2=4 1*3=3 2*3=6 3*3=9 1*4=4 2*4=8 3*4=12 4*4=16 1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81['0001.lkbjmbfcwj', '0002.ciebvklpie', '0003.sjwtcakjjk', '0004.kuiivvfoai', '0005.ymaetkbdrt', '0006.ayhlrgedoh', '0007.xdjnaysdct', '0008.qkakrtdebv', '0009.jytyhtnwkc', '0010.rbxkiuetev', '0011.plhdxcdyvq', '0012.ubkudcrisb', '0013.yoceaqjvna', '0014.aeirhriutw', '0015.yemotxgfin', '0016.tehmlunsgy', '0017.seobircuxq', '0018.nxofutxipl', '0019.lbtmvkrhnj', '0020.rowntjaqpp', '0021.oadngppkty', '0022.ftdeifipph', '0023.fwuxgxgovt', '0024.bjnaxoqsxd', '0025.jhkjanttrr', '0026.eoutbjinyq', '0027.agdidptkcu', '0028.ccofruyutd', '0029.suchksvbva', '0030.ucvrshekrf', '0031.qikrlpilqi', '0032.ffdfqosxnh', '0033.jtotgqsdgm', '0034.jxssbjnclg', '0035.qandynxfat', '0036.ygodstktip', '0037.qklhxypdba', '0038.vlghicldkp', '0039.jbpyieqxkc', '0040.dcybelgsew', '0041.bumewnipnp', '0042.koqdtxfain', '0043.wpjdhnduah', '0044.vledqpcnpd', '0045.bkjisgagaj', '0046.ymdthjiphw', '0047.avqxthoilm', '0048.wsxtulxfnl', '0049.tmvdcqovcf', '0050.jcfnuaqfob', '0051.tpptnvysyv', '0052.bsmfywydnw', '0053.ivqotuhhgp', '0054.nfryeqntta', '0055.eyoxwwtuhl', '0056.hgtnxluwqy', '0057.buabekigsu', '0058.dxbflmyknn', '0059.bibmwmoitm', '0060.mmbyibfeeg', '0061.ulythfirrd', '0062.rnamiseafs', '0063.abpbtceqpd', '0064.fawoscqiub', '0065.aunqntadxh', '0066.owavtvxdrq', '0067.ahnioayayy', '0068.ojbuyqvmxf', '0069.svbqsppkes', '0070.ncqojtdtlg', '0071.hmbtvsuwah', '0072.iwqykfsisp', '0073.fymolgcbnh', '0074.txhnidqufy', '0075.icmhrnifjx', '0076.dvctqrjyhe', '0077.nqncmelbys', '0078.gbaqnpaxyy', '0079.gfirdjcrao', '0080.qcguhuqdwk', '0081.kuqellfomi', '0082.kpltlguvcc', '0083.lfeserogau', '0084.imgwnglrob', '0085.dvtcjupmmk', '0086.evswireebh', '0087.tlbordvirb', '0088.eleixowhur', '0089.mvpwqiottn', '0090.iokdlfvipt', '0091.tqeuiulywc', '0092.twrfdissos', '0093.ylbtevnroy', '0094.uvtifqqdny', '0095.kxrhorowny', '0096.qcygokxvys', '0097.gvlufbmctq', '0098.jmqgjidgxv', '0099.gxvbreoimr', '0100.ljjjoelvna']‘0001.ababsdgcfe’ 這樣的id ,從0001 - 0100
lst = [i **2 for i in range(1, 11)]lst = [1,2,3,4,5] newlist = [lst[i] + lst[i + 1] for i in range(len(lst) - 1)] print(newlist) # [3, 5, 7, 9]cf = [ print('{}*{}={:<2}'.format(j, i, i * j), end='\n' if i == j else ' ') for i in range(1, 10) for j in range(1, i + 1)]print(cf)print('\n'.join([' '.join(['{}*{}={:<2}'.format(j, i, i * j) for j in range(1, i + 1)] ) for i in range(1, 10) ]))import random alpha = bytes(range(97,122)).decode()# lst = ['{:04}.{}'.format(i,''.join([random.choice(alpha) for _ in range(10)])) for i in range(1, 101)] # print(lst)l = random.choices(alpha,k = 10) # ['u', 't', 'h', 'x', 'v', 'g', 'c', 'p', 'l', 'n'] s1 = ''.join(l)l = ''.join(random.sample(alpha,10)) # 如果用sample的話,就沒有重復的字母,上面的choice 或choices是有重復字母的可能性的 print(l)2、生成器表達式:
定義:
生成器就是迭代器,可以理解為一種數據類型,這種數據類型實現了迭代器協議,其他的數據類型需要調用自己內置的__iter_方法,所以生成器就是可迭代對象。
生成器分類以及在Python中的表現形式:(Python有兩種不同的方式提供生成器)
①生成器函數:常規函數定義,但是,使用yield 語句代替return語句,但是,yield在同一層函數中,可以多次使用,一次返回一個結果,返回一個結果后,將函數設置為掛起狀態,以便下次從他離開的地方繼續執行。
②生成器表達式:類似于列表的推導,但是生成器返回按需產生結果的一個對象,而不是一次性構建一個結果列表。
語法:
- (返回值 for 元素 in 可迭代對象 if 條件)
- 列表解析式的中括號換成小括號
- 返回一個生成器
和列表解析式的區別:
- 生成器表達式是按需計算(或惰性求值,延遲計算)需要的時候才算值。
- 列表解析式是立即返回值
生成器:
- 可迭代對象
- 迭代器
舉例:
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' g = ('{:04}'.format(i) for i in range(1,11)) print(g)a = next(g)for i in g:print('i',i) print('------------------') for j in g:print('j',j)結果:
# 可以看出g 是一個生成器對象 generator # next(g) 表示地址指針向下走一步 # 第一個for循環就將g 迭代完了 # 所以第二個for就沒法往下進行迭代 # 因為生成器是無法向列表那樣,一致迭代,當地址指針到了最后一個后,用next() 再迭代會報錯 <generator object <genexpr> at 0x0000000001D9D318> i 0002 i 0003 i 0004 i 0005 i 0006 i 0007 i 0008 i 0009 i 0010 ------------------對比:列表解析式:
g = ['{:04}'.format(i) for i in range(1,11)] print(g)for i in g:print('i',i) print('------------------') for j in g:print('j',j)['0001', '0002', '0003', '0004', '0005', '0006', '0007', '0008', '0009', '0010'] i 0001 i 0002 i 0003 i 0004 i 0005 i 0006 i 0007 i 0008 i 0009 i 0010 ------------------ j 0001 j 0002 j 0003 j 0004 j 0005 j 0006 j 0007 j 0008 j 0009 j 0010總結:
生成器,延遲計算(惰性求值),返回迭代器,可以迭代,從前往后走一遍,不能回頭。
列表解析式:立即求值,返回的不是迭代器,是可迭代對象,從前往后走一遍后,可以回頭
注:
it = (print('{}'.format(i + 1)) for i in range(2))first = next(it)second = next(it)val = first + second1 2 -------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-10-8a69cb4a56e0> in <module>()5 second = next(it)6 ----> 7 val = first + secondTypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'# 事實上,it 生成器(generator)里邊是None,print 是打印, # 所以每次next(it) 的時候,要執行一次print(...),同時將None 賦值給變量例子
it = (x for x in range(10) if x %2)first = next(it)second = next(it)val = first + secondprint(val) # 4生成器和列表解析式的對比:
- 計算方式:
生成器表達式延遲計算,列表解析式立即計算 - 內存占用:
單從返回值本身來說,生成器表達式省內存,列表解析式能返回新的列表
生成器沒有數據,內存占用極少,但是使用的時候,雖然一個個返回數據,但是合起來占用的內存也差不多
列表解析式構造新的列表需要占用內存 - 計算速度:
單看計算時間看,生成器表達式好事非常短,列表解析式耗時長
但是生成器本身并沒有返回任何值,只返回一個生成器對象
列表解析式構造并返回一個新的列表
注:
使用內建函數 iter() 可以將一個可迭代對象轉換為一個生成器。iter([1,2,3])
b = iter(range(4))next(b) # 一直是0 ,因為每next一次,從新建一個生成器,所以一直在0的位置a = iter(range(4))for i in a :print(i) # 0,1,2,3,迭代器沒有 len() 這個attribution
3、集合解析式 Python3.x新增
語法:
{ 返回值 for 元素 in 可迭代對象 if 條件}
列表解析式的中括號,換位大括號
立即返回一個集合
用法:
{ (x, x + 1) for i in range(10) } { [x] for x in range(10)} # 這個會報錯,[x ] ,集合中 不能有不可hash的4、字典解析:Python3 新增
語法:
{ 返回值 for 元素 in 可迭代對象 if 條件}
使用 k-v 形式
立即返回一個字典
用法:
a = {x:(x, x + 1) for x in range(4)} print(a) # {0: (0, 1), 1: (1, 2), 2: (2, 3), 3: (3, 4)} b = {x:[x, x + 1] for x in range(4)} print(b) # {0: [0, 1], 1: [1, 2], 2: [2, 3], 3: [3, 4]} c = {(x,):[x, x + 1] for x in range(4)} print(c) # {(0,): [0, 1], (1,): [1, 2], (2,): [2, 3], (3,): [3, 4]} d = {[x]:[x, x + 1] for x in range(4)} print(d) # TypeError e = {chr(0x41 + x):x ** 2 for x in range(4)} print(e) # {'A': 0, 'B': 1, 'C': 4, 'D': 9} f = {str(x):y for x in range(4) for y in range(3)} print(f) # {'0': 2, '1': 2, '2': 2, '3': 2} 覆蓋5、總結:
——生成器相對解析式而言,生成器主要節省了內存,事實上,效率上并沒有明顯的提高,所以一般只考慮內存問題就可以。
——Python2 映入列表解析式
——Python2.4 引入生成器表達式
——Python3 引入集合,字典解析式,并遷移到2.7
——一般來說,應該多用解析式,簡短,高效,如果一個解析式非常復雜,要考慮拆解用for循環
——生成器和迭代器是不同的對象,但是都可迭代對象,迭代器可以用next()
——生成器是迭代器,迭代器不一定是生成器, iter(range(4)) 不是生成器生成的
總結
以上是生活随笔為你收集整理的Python-各种结构解析以及生成器(列表解析,字典解析,集合解析,元组构成的生成器)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python-functools (re
- 下一篇: python socket实现文件传输(