python各種推導(dǎo)式(超級詳細(xì))

推導(dǎo)式comprehensions(又稱解析式)辽幌,是Python的一種獨有特性。推導(dǎo)式是可以從一個數(shù)據(jù)序列構(gòu)建另一個新的數(shù)據(jù)序列的結(jié)構(gòu)體。 共有三種推導(dǎo)墙歪,在Python2和3中都有支持:

  • 列表(list)推導(dǎo)式
  • 字典(dict)推導(dǎo)式
  • 集合(set)推導(dǎo)式

  • 列表推導(dǎo)式

基本格式為:
[表達(dá)式 for 變量 in 列表] 或者 [表達(dá)式 for 變量 in 列表 if 條件]

具體可分為兩種:

* [x for x in data if condition]

此處if主要起條件判斷作用,data數(shù)據(jù)中只有滿足if條件的才會被留下贝奇,最后統(tǒng)一生成為一個數(shù)據(jù)列表虹菲。

* [exp1 if condition else exp2 for x in data]

此處if...else主要起賦值作用,當(dāng)data中的數(shù)據(jù)滿足if條件時將其做exp1處理掉瞳,否則按照exp2處理毕源,最后統(tǒng)一生成為一個數(shù)據(jù)列表

為了加深理解我們舉個例子
variable = [out_exp_res for out_exp in input_list if out_exp == 2]
out_exp_res:  列表生成元素表達(dá)式,可以是有返回值的函數(shù)
for out_exp in input_list:  迭代input_list將out_exp傳入out_exp_res表達(dá)式中
if out_exp == 2:  根據(jù)條件過濾哪些值可以

我們可以再舉幾個例子:

multiples = [i for i in range(30) if i % 3 == 0]
print(multiples)
Output: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

multiples = [squared(i) for i in range(30) if i % 3 == 0]
print multiples
Output: [0, 9, 36, 81, 144, 225, 324, 441, 576, 729]

data = ['driver', '2017-07-13', 1827.0, 2058.0, 978.0, 1636.0, 1863.0, 2537.0, 1061.0]
(1)若我要取得以上列表中值大于2000的數(shù)值陕习,這里可以使用列表推導(dǎo)式的形式①: [x for x in data if x > 2000] 得到如下結(jié)果(字符串類型數(shù)據(jù)被認(rèn)為是無窮大數(shù)):['driver', '2017-07-13', 2058.0, 2537.0]
(2)若要解決我上面提到的問題霎褐,則需要使用列表推導(dǎo)式的形式② : [int(x) if type(x) == float else x for x in data] 得到結(jié)果:['driver', '2017-07-13', 1827, 2058, 978, 1636, 1863, 2537, 1061]

兩個例子肯定不夠理解的,我們要實戰(zhàn)一下该镣,親自上手敲敲代碼
例1:過濾掉長度小于或等于3的字符串列表冻璃,并將剩下的轉(zhuǎn)換成大寫字母:

>>> names = ['Bob','Tom','alice','Jerry','Wendy','Smith']
>>> new_names = [name.upper()for name in names if len(name)>3]
>>> print(new_names)
['ALICE', 'JERRY', 'WENDY', 'SMITH']

例2:生成間隔5分鐘的時間列表序列:

>>> time = ['%.2d:%.2d'%(h,m )for h in range(24) for m in range(0,60,5) ]
>>> print(time)
['00:00', '00:05', '00:10', '00:15', '00:20', '00:25', '00:30', '00:35', '00:40', '00:45', '00:50', '00:55', '01:00', '01:05', '01:10', '01:15', '01:20', '01:25', '01:30', '01:35', '01:40', '01:45', '01:50', '01:55', '02:00', '02:05', '02:10', '02:15', '02:20', '02:25', '02:30', '02:35', '02:40', '02:45', '02:50', '02:55', '03:00', '03:05', '03:10', '03:15', '03:20', '03:25', '03:30', '03:35', '03:40', '03:45', '03:50', '03:55', '04:00', '04:05', '04:10', '04:15', '04:20', '04:25', '04:30', '04:35', '04:40', '04:45', '04:50', '04:55', '05:00', '05:05', '05:10', '05:15', '05:20', '05:25', '05:30', '05:35', '05:40', '05:45', '05:50', '05:55', '06:00', '06:05', '06:10', '06:15', '06:20', '06:25', '06:30', '06:35', '06:40', '06:45', '06:50', '06:55', '07:00', '07:05', '07:10', '07:15', '07:20', '07:25', '07:30', '07:35', '07:40', '07:45', '07:50', '07:55', '08:00', '08:05', '08:10', '08:15', '08:20', '08:25', '08:30', '08:35', '08:40', '08:45', '08:50', '08:55', '09:00', '09:05', '09:10', '09:15', '09:20', '09:25', '09:30', '09:35', '09:40', '09:45', '09:50', '09:55', '10:00', '10:05', '10:10', '10:15', '10:20', '10:25', '10:30', '10:35', '10:40', '10:45', '10:50', '10:55', '11:00', '11:05', '11:10', '11:15', '11:20', '11:25', '11:30', '11:35', '11:40', '11:45', '11:50', '11:55', '12:00', '12:05', '12:10', '12:15', '12:20', '12:25', '12:30', '12:35', '12:40', '12:45', '12:50', '12:55', '13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55', '14:00', '14:05', '14:10', '14:15', '14:20', '14:25', '14:30', '14:35', '14:40', '14:45', '14:50', '14:55', '15:00', '15:05', '15:10', '15:15', '15:20', '15:25', '15:30', '15:35', '15:40', '15:45', '15:50', '15:55', '16:00', '16:05', '16:10', '16:15', '16:20', '16:25', '16:30', '16:35', '16:40', '16:45', '16:50', '16:55', '17:00', '17:05', '17:10', '17:15', '17:20', '17:25', '17:30', '17:35', '17:40', '17:45', '17:50', '17:55', '18:00', '18:05', '18:10', '18:15', '18:20', '18:25', '18:30', '18:35', '18:40', '18:45', '18:50', '18:55', '19:00', '19:05', '19:10', '19:15', '19:20', '19:25', '19:30', '19:35', '19:40', '19:45', '19:50', '19:55', '20:00', '20:05', '20:10', '20:15', '20:20', '20:25', '20:30', '20:35', '20:40', '20:45', '20:50', '20:55', '21:00', '21:05', '21:10', '21:15', '21:20', '21:25', '21:30', '21:35', '21:40', '21:45', '21:50', '21:55', '22:00', '22:05', '22:10', '22:15', '22:20', '22:25', '22:30', '22:35', '22:40', '22:45', '22:50', '22:55', '23:00', '23:05', '23:10', '23:15', '23:20', '23:25', '23:30', '23:35', '23:40', '23:45', '23:50', '23:55']

例3: 求(x,y),其中x是0-5之間的偶數(shù),y是0-5之間的奇數(shù)組成的元祖列表:

list = [(x,y) for x in range(5) if x%2 == 0 for y in range(5) if y%2 == 1]
print(list)

D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]

Process finished with exit code 0

例4: 求M中3,6,9組成的列表:

M = [[1,2,3],[4,5,6],[7,8,9]]
list_1 = [row[2] for row in M]
print(list_1)

D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
[3, 6, 9]

Process finished with exit code 0

例5: 求M中斜線1,5,9組成的列表:

M = [[1,2,3],[4,5,6],[7,8,9]]
list_1 = [M[x][x] for x in range(len(M)) ]
print(list_1)

D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
[1, 5, 9]

Process finished with exit code 0

例6: 求M,N中矩陣和元素的乘積:

M = [[1,2,3],[4,5,6],[7,8,9]]
N = [[2,2,2],[3,3,3], [4,4,4]]
list = [M[row][col]*N[row][col] for row in range(3) for col in range(3)]
print(list)

D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
[2, 4, 6, 12, 15, 18, 28, 32, 36]

Process finished with exit code 0

注意:

使用()生成generator:
將倆表推導(dǎo)式的[]改成()即可得到生成器。

multiples = (i for i in range(30) if i % 3 is 0)
print(type(multiples))

Output: <type 'generator'>
  • 字典推導(dǎo)式

我們看先來看使用字典推導(dǎo)式的基礎(chǔ)模板:{ key:value for key,value in existing_data_structure }
這里和list有所不同省艳,因位dict里面有兩個關(guān)鍵的屬性娘纷,key 和 value,但大同小異跋炕,我們現(xiàn)在的expression部分可以同時對 key 和 value 進(jìn)行操作
下面來看最常見的應(yīng)用
例1: 用字典推導(dǎo)式配合枚舉的使用案例:

strings = ['import','is','with','if','file','exception','shim','lucy']
dict = {k:v for v,k in enumerate(strings)}
print(dict)
*********************************
D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
{'import': 0, 'is': 1, 'with': 2, 'if': 3, 'file': 4, 'exception': 5, 'shim': 6, 'lucy': 7}

Process finished with exit code 0

從這個例題我們發(fā)散一下赖晶,上題的k是字符串,v是序列辐烂。如果我們更換kv呢:

strings = ['import','is','with','if','file','exception','shim','lucy']
dict = {k:v for k,v in enumerate(strings)}
print(dict)
*************************
D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
{0: 'import', 1: 'is', 2: 'with', 3: 'if', 4: 'file', 5: 'exception', 6: 'shim', 7: 'lucy'}

Process finished with exit code 0

顯然中間的kv就是控制鍵值的遏插。
關(guān)于enumerate()函數(shù)請參考:https://www.runoob.com/python/python-func-enumerate.html
例2:互換key和value的值:

person = {'角色名':'宮本武藏','定位':'刺客'}
person_reverse = {k:v for v,k in person.items()}
#person_reverse = {v:k for k,v in person.items()}#也可以實現(xiàn)
print(person_reverse)
******************************************
D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
{'宮本武藏': '角色名', '刺客': '定位'}

Process finished with exit code 0

例3:源數(shù)據(jù)的key是字母的大小寫混在一起,我們想統(tǒng)計同一個字母(不論大小寫)的key所對應(yīng)的鍵值對的和:

nums = {'a':10,'b':20,'A':5,'B':3,'d':4}
num_frequency  = {k.lower():nums.get(k.lower(),0) + nums.get(k.upper(),0)
                  for k in nums.keys() }
#nums是字典纠修,nums.get(k.lower(),0)的意思是在字典nums中查找小寫Key
#找到了返回KEY對應(yīng)的Value,否則返回參數(shù)0,nums.get(k.upper(),0)同上
print(num_frequency)
*******************
D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
{'a': 15, 'b': 23, 'd': 4}

Process finished with exit code 0

例4:我們有一個fruit的list涩堤,現(xiàn)在想要得到每一種水果的單詞長度:

fruits = ['apple','orange','banana','mango','peach']
fruits_dict = {fruit:len(fruit) for fruit in fruits}
print(fruits_dict)
********************************************
D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
{'apple': 5, 'orange': 6, 'banana': 6, 'mango': 5, 'peach': 5}

Process finished with exit code 0
  • 集合推導(dǎo)式(Set comprehensions)

讓我們看先來看使用集合推導(dǎo)式的基礎(chǔ)模板:{ expression for item in Sequence if conditional }
其實集合推導(dǎo)式和list的推導(dǎo)式很像,但是既然是集合分瘾,肯定會配合利用Set的特有屬性來實現(xiàn)我們的目的胎围。
對Set數(shù)據(jù)結(jié)構(gòu)不夠了解,推薦參考:https://segmentfault.com/a/1190000018109634?_ea=7068836

例1:首先德召,我們來看一個根據(jù)Set值唯一的特性的例子白魂,我們有一個list叫names,用來存儲名字上岗,其中的數(shù)據(jù)很不規(guī)范福荸,有大寫,小寫肴掷,還有重復(fù)的敬锐,我們想要去重并把名字的格式統(tǒng)一為首字母大寫,實現(xiàn)方法便是用Set推導(dǎo)式:

names = [ 'Bob', 'JOHN', 'alice', 'bob', 'ALICE', 'James', 'Bob','JAMES','jAMeS' ]
new_names = {n[0].upper() + n[1:].lower() for n in names}
print(new_names)
***********************************************************
D:\anaconda\python.exe D:/bilibili大學(xué)/簡書代碼/推導(dǎo)式.py
{'Bob', 'James', 'John', 'Alice'}

Process finished with exit code 0

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呆瞻,一起剝皮案震驚了整個濱河市台夺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌痴脾,老刑警劉巖颤介,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赞赖,居然都是意外死亡滚朵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門前域,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辕近,“玉大人,你說我怎么就攤上這事匿垄∫普” “怎么了归粉?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吞杭。 經(jīng)常有香客問我盏浇,道長变丧,這世上最難降的妖魔是什么芽狗? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮痒蓬,結(jié)果婚禮上童擎,老公的妹妹穿的比我還像新娘。我一直安慰自己攻晒,他們只是感情好顾复,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鲁捏,像睡著了一般芯砸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上给梅,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天假丧,我揣著相機(jī)與錄音,去河邊找鬼动羽。 笑死包帚,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的运吓。 我是一名探鬼主播渴邦,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拘哨!你這毒婦竟也來了谋梭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤倦青,失蹤者是張志新(化名)和其女友劉穎章蚣,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姨夹,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡纤垂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了磷账。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峭沦。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖逃糟,靈堂內(nèi)的尸體忽然破棺而出吼鱼,到底是詐尸還是另有隱情蓬豁,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布菇肃,位于F島的核電站地粪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏琐谤。R本人自食惡果不足惜蟆技,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斗忌。 院中可真熱鬧质礼,春花似錦、人聲如沸织阳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽唧躲。三九已至造挽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弄痹,已是汗流浹背饭入。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留界酒,地道東北人圣拄。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像毁欣,于是被迫代替她去往敵國和親庇谆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容