6個Python超酷技巧阅懦,原來還能這樣用!初學(xué)必看

0徘铝、引言

不管學(xué)什么耳胎,我個人是非常喜歡小技巧(tricks)的,Python 也不例外惕它。著名 Python 技巧大師 Dan Bader 是這樣定義 Python Tricks 的怕午。

A Python Trick either teaches an aspect of Python with a simple illustration, or it serves as a motivating example, enabling you to dig deeper and develop an intuitive understanding.

Dan Bader

Python Trick 表現(xiàn)簡單而直觀,但可以激發(fā)你繼續(xù)深挖的興趣淹魄,你會說“原來還可以這樣做啊”郁惜。

今天就來介紹6個我最喜歡的 Trick,使用它們可以讓你的代碼更 Pythonic:

下劃線占位符

枚舉

打包

解包

動態(tài)屬性

密碼函數(shù)

它們都非常直觀而簡單甲锡,相信讀完之后兆蕉,肯定有幾個技巧會讓你驚嘆到,原來 Python 還可以這么用缤沦。

1虎韵、下劃線占位符

有時候數(shù)字一大,數(shù)起來會犯迷糊缸废,看下例包蓝。

apple_mktcap=1084000000000facebook_mktcap?=458870000000total = apple_mktcap + facebook_mktcapprint(total)

1542870000000.0

這個蘋果和臉書的市值之和有多少個零啊企量?數(shù)不清楚是吧测萎,在 Python 中,我們可以用下劃線占位符(underscore placeholder)來將大數(shù)每三位數(shù)分段届巩。請注意硅瞧,多加了下劃線,數(shù)字還是數(shù)值型變量姆泻,只是讓我們?nèi)菀妆嬲J(rèn)大數(shù)零酪。

apple_mktcap=1_084_000_000_000facebook_mktcap =458_870_000_000total = apple_mktcap + facebook_mktcapprint(total)

1542870000000

你看,加個下劃線的數(shù)字還是可以相加拇勃,但是結(jié)果還是不好認(rèn)四苇。還記得 f string 格式化字符串嗎?用 :, 來每三位數(shù)分段方咆。

print(f'Total is{total:,}USD')

Totalis1,542,870,000,000USD

“下劃線占位符”解決痛點:容易辨認(rèn)大數(shù)的位數(shù)月腋。

2、枚舉

給定一列表,包含四種計算機語言的元素榆骚。

languages= ['Python','R','Matlab','Julia']

如果我們想把每中語言附加對應(yīng)的索引一來打印出來片拍,怎么寫代碼呢?最直接的想法就是初始化 index 為 0妓肢,然后在運行每個 for 循環(huán)后將 index 的值加 1捌省,代碼如下。

index= 0for lang in languages:print(index, lang)index+=1

0Python1R2Matlab3Julia

結(jié)果是對的碉钠,但是這代碼你不覺得很丑嗎纲缓?很不 Pythonic 嗎?

Python 有 enumerate() 函數(shù)可以一次性返回列表(任意迭代器)的元素以及其對應(yīng)的索引喊废,代碼如下祝高,優(yōu)雅嗎?

forindex, lang in enumerate(languages):print(index, lang)

0Python1R2Matlab3Julia

除此之外污筷,你還可以自定義索引的初始值工闺。在實際生活中,一般索引從 1 開始更自然瓣蛀,那么將參數(shù) start 設(shè)置為 1 就好了陆蟆。

forindex, lang in enumerate(languages, start=1):print(index, lang)

1Python2R3Matlab4Julia

“枚舉函數(shù) enumerate()”解決痛點:不需要顯性創(chuàng)建索引。

3惋增、打包

給定一串名字(names)和演員角色(actors)遍搞,用兩個列表存儲。

names= ['小羅伯特唐尼','托比·馬奎爾','克里斯蒂安·貝爾','杰森·莫瑪']actors = ['鋼鐵俠','蜘蛛俠','蝙蝠俠','水行俠']

如果我們想把每個名字和角色一一對應(yīng)起來器腋,可以用上節(jié)學(xué)到的 enumerate() 函數(shù)。我們可以返回 names 里的元素和索引钩杰,再用索引來獲取 actors 里的元素纫塌,代碼如下。

forindex, nameinenumerate(names):? ? print(f'{name}是{actors[index]}')

小羅伯特唐尼是鋼鐵俠

托比·馬奎爾是蜘蛛俠

克里斯蒂安·貝爾是蝙蝠俠

杰森·莫瑪是水行俠

結(jié)果是對的讲弄,但是代碼不夠優(yōu)雅措左。來糖儡,zip() 函數(shù)了解一下线定?

forname, actorinzip(names, actors):? ? print(f'{name}是{actor}')

小羅伯特唐尼是鋼鐵俠

托比·馬奎爾是蜘蛛俠

克里斯蒂安·貝爾是蝙蝠俠

杰森·莫瑪是水行俠

zip() 函數(shù)將列表(迭代器)中對應(yīng)的元素打包成一個個元組村斟,然后返回由這些元組組成的列表饰迹。上面代碼是不是漂亮多了懈万。

再加一個列表如何榆鼠?zip() 函數(shù)表示毫無壓力踊跟。

universes= ['漫威','漫威','DC','DC']

forname, actor, universeinzip(names, actors, universes):? ? print(f'{name}是來自{universe}的{actor}')

小羅伯特唐尼是來自漫威的鋼鐵俠

托比·馬奎爾是來自漫威的蜘蛛俠

克里斯蒂安·貝爾是來自DC的蝙蝠俠

杰森·莫瑪是來自DC的水行俠

讓我們再看一次 zip() 函數(shù)的用法阁危,其?3?個參數(shù) names, actors 和 universes 列表中都有?4個元素群井,那么在對應(yīng)的位置 i(從 0 到 3)一個個獲取 names[i], actors[i] 和 universes[i]状飞,并打包成新列表,因此輸出是?4?個列表,每個列表有?3?個元素诬辈。

a= zip(names, actors, universes)print(*a)

('小羅伯特唐尼','鋼鐵俠','漫威')('托比·馬奎爾','蜘蛛俠','漫威')('克里斯蒂安·貝爾','蝙蝠俠','DC')('杰森·莫瑪','水行俠','DC')

結(jié)果沒問題酵使。需要注意的是 a 實際上是個對象,要看它里面的內(nèi)容焙糟,需要在 a 前面加個 * 字符口渔。

你們現(xiàn)在肯定會想,有了 zip()穿撮,那有沒有其反向操作的 unzip() 呢缺脉?答案是沒有,zip() 的反向操作還是 .... zip()!!!

你品混巧,你細(xì)品枪向。

a =zip(names, actors, universes)names, actors, universes =zip(*a)print(names, actors, universes)

('小羅伯特唐尼','托比·馬奎爾','克里斯蒂安·貝爾','杰森·莫瑪')('鋼鐵俠','蜘蛛俠','蝙蝠俠','水行俠')('漫威','漫威','DC','DC')

“打包函數(shù)?zip()”解決痛點:能同時遍歷多個迭代器

4咧党、解包

一個簡單例子秘蛔,將 1 和 2 分別賦給 a 和 b,這種操作稱為解包(unpack)傍衡。

a, b =1,2print(a)print(b)

12

如果你不想要 b 的話深员,用下劃線代替就行了。

a, _ =1,2print(a)

1

但如果等號左右兩邊元素和變量個數(shù)不一樣蛙埂。程序會報錯倦畅。

a,b,c=1,2

---------------------------------------------------------------------------ValueError Traceback (most recentcalllast)in----> 1 a, b, c = 1, 2ValueError:notenoughvaluestounpack (expected3, got2)

用 * 字符可以解決這個問題。將右邊的 1 和 2 分別解包給 a 和 b绣的,那么什么都不剩了叠赐,因此 c 得到的是個空集 []。

a, b, *c=1, 2print(a)print(b)print(c)

12[]

如果右邊元素多過左邊變量呢屡江?從頭開始一一解包芭概,再把多余的全部賦給 c。

a, b, *c=1,2,3,4, 5print(a)print(b)print(c)

12[3,4,5]

更進(jìn)一步惩嘉,我們還可以從頭和尾開始一一解包罢洲,再把多余的全部賦給 c。

a, b, *c, d =1,2,3,4, 5print(a)print(b)print(c)print(d)

12[3,4]5

不想要 c 的話文黎,用 *_ 將其代替即可惹苗。

a,b,*_,d=1,2,3,4,5print(a)print(b)print(d)

125

“解包”解決痛點:將值賦給正確的變量。

5耸峭、動態(tài)屬性

這個技巧是我覺得最有用的桩蓉。首先定一個金融產(chǎn)品的類?Instrument,并創(chuàng)建一個對象 inst劳闹。

classInstrument():passinst = Instrument()

定義 inst 的兩個屬性并賦值触机,本金(notional)和到期日(maturity)帚戳。

inst.notional=100_000_000inst.maturity ='2025-03-25'

print(inst.notional)print(inst.maturity)

1000000002025-03-25

現(xiàn)在將屬性 notional 和其屬性值 10000000 存儲在變量 first_key 和 first_val 中。

first_key='notional'first_val =100_000_000

我們想用?first_key 的值 notional(而不是 first_key 這個字符)來作為屬性儡首。

inst= Instrument()inst.first_key = first_val

打印 inst.notional 會報錯片任,錯誤是 Instrument 對象中沒有 notional 這樣的屬性名。

print(inst.notional)

---------------------------------------------------------------------------AttributeError Traceback (most recentcalllast)in----> 1 print(inst.notional)AttributeError:'Instrument'objecthasnoattribute'notional'

原因是 inst 把 first_key 這個字符串當(dāng)成屬性名蔬胯,驗證如下对供。

print(inst.first_key)

100000000

怎么解決這個動態(tài)屬性的問題呢?即我們要變量的值為屬性名氛濒,而不是變量本身名稱當(dāng)屬性名产场。用 setattr() 函數(shù),它有三個參數(shù):

參數(shù) 1 - 對象

參數(shù) 2 - 屬性名的變量名

參數(shù) 3 - 屬性值的變量名

代碼如下舞竿,這時用 inst.notional 不會報錯了京景。

inst= Instrument()setattr(inst, first_key, first_val)print(inst.notional)

100000000

和 setattr() 相對應(yīng),你可以用 getattr() 函數(shù)來獲取屬性值骗奖,它有兩個參數(shù):

參數(shù) 1 - 對象

參數(shù) 2 - 屬性名的變量名

代碼如下:

getattr(inst, first_key)

100000000

和靜態(tài)屬性相比确徙,動態(tài)屬性到底好在哪里呢?以讀取歐式期權(quán)的特征舉例执桌,通常信息以字典(也有其他格式)存儲鄙皇,具體內(nèi)容如下:

inst_info = {'ID':'9001001','EffectiveDate':'2020-03-20','MaturityDate':'2020-06-20','Notional':10_000_000,'DomesticCurrency':'USD','ForeignCurrency':'EUR','Flavor':'Put','Strike':1.08,'Display':'domestic?pips','AssetClass':'FX','Instrument?Type':'EuropeanOption','Model':'Heston'}

那么當(dāng)我們創(chuàng)建 inst 對象時,把上面字典的鍵(key)作為屬性名仰挣。每種產(chǎn)品具體的特征都不一樣伴逸,如果用靜態(tài)屬性的將字典轉(zhuǎn)成對象的話,代碼會非常亂而且無法管理膘壶,但如果用動態(tài)屬性的話错蝴,下面三行代碼就能搞定(用 setattr())。

inst= Instrument()for key, val in inst_info.items():? ? setattr(inst, key, val)

用 getattr() 函數(shù)來打印出來看結(jié)果對不對颓芭,兩行代碼搞定漱竖。

forkeyininst_info.keys():print( key,'|', getattr(inst, key))

ID?|9001001EffectiveDate |?2020-03-20MaturityDate?| 2020-06-20Notional|?10000000DomesticCurrency?| USDForeignCurrency |?EURFlavor?|PutStrike|?1.08Display?|domestic pipsAssetClass |?FXInstrumentType?| European OptionModel|?Heston

結(jié)果是對的,但也是丑的畜伐,用 f string 來添加若干個空白,將每個屬性值的起始位置對齊躺率。

forkeyininst_info.keys():print( f'{key:18s}|', getattr(inst, key))

ID?|9001001EffectiveDate |?2020-03-20MaturityDate?| 2020-06-20Notional|?10000000DomesticCurrency?| USDForeignCurrency |?EURFlavor?|PutStrike|?1.08Display?|domestic pipsAssetClass |?FXInstrumentType?| European OptionModel|?Heston

“動態(tài)屬性 setattr()”解決痛點:用盡可能少的代碼快速創(chuàng)建對象玛界。

6、密碼函數(shù)

當(dāng)?shù)卿洉r悼吱,你需要輸入你的用戶名和密碼慎框,用 input() 函數(shù)可以做到要求用戶主動輸入,但是輸入的密碼任何人都可見后添,這還是密碼嗎笨枯?

username =input('Username: ')password =input('Password: ')print('Logging In...')

Username:StevenPassword:?1031LoggingIn ...

用 getpass() 函數(shù)即可,不解釋,自己看下圖馅精。

fromgetpassimportgetpassusername = input('Username: ')password = getpass('Password: ')print('Logging In...')

Username:StevenPassword:········LoggingIn ...

“密碼函數(shù) getpass()”解決痛點:讓輸入的密碼不可見严嗜。

7、總結(jié)

六個小技巧洲敢,簡單直觀漫玄,但是超級有用。有時候就是用這樣的一個函數(shù)压彭,你不知道睦优,寫出來的代碼不優(yōu)雅;你知道了壮不,寫出來的代碼真好看汗盘。

六個技巧總結(jié)如下:

下劃線占位符:容易辨認(rèn)大數(shù)的位數(shù)

枚舉函數(shù)?enumerate():不需要顯性創(chuàng)建索引

打包函數(shù)?zip():能同時遍歷多個迭代器

解包:將值賦給正確的變量

動態(tài)屬性?setattr():用盡可能少的代碼快速創(chuàng)建對象

密碼函數(shù)?getpass():讓輸入的密碼不可見

用起來,酷起來询一。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末隐孽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子家凯,更是在濱河造成了極大的恐慌缓醋,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绊诲,死亡現(xiàn)場離奇詭異送粱,居然都是意外死亡,警方通過查閱死者的電腦和手機掂之,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門抗俄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人世舰,你說我怎么就攤上這事动雹。” “怎么了跟压?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵胰蝠,是天一觀的道長。 經(jīng)常有香客問我震蒋,道長茸塞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任查剖,我火速辦了婚禮钾虐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘笋庄。我一直安慰自己效扫,他們只是感情好倔监,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著菌仁,像睡著了一般浩习。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掘托,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天瘦锹,我揣著相機與錄音,去河邊找鬼闪盔。 笑死弯院,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泪掀。 我是一名探鬼主播听绳,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼异赫!你這毒婦竟也來了椅挣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤塔拳,失蹤者是張志新(化名)和其女友劉穎鼠证,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體靠抑,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡量九,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了颂碧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荠列。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖载城,靈堂內(nèi)的尸體忽然破棺而出肌似,到底是詐尸還是另有隱情,我是刑警寧澤诉瓦,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布川队,位于F島的核電站,受9級特大地震影響睬澡,放射性物質(zhì)發(fā)生泄漏固额。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一猴贰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧河狐,春花似錦米绕、人聲如沸瑟捣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迈套。三九已至,卻和暖如春碱鳞,著一層夾襖步出監(jiān)牢的瞬間桑李,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工窿给, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贵白,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓崩泡,卻偏偏與公主長得像禁荒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子角撞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355