Python 是一門(mén)運(yùn)用很廣泛的語(yǔ)言庆械,自動(dòng)化腳本薇溃、爬蟲(chóng),甚至在深度學(xué)習(xí)領(lǐng)域也都有 Python 的身影缭乘。作為一名前端開(kāi)發(fā)者沐序,也了解 ES6 中的很多特性借鑒自 Python (比如默認(rèn)參數(shù)、解構(gòu)賦值堕绩、Decorator等)策幼,同時(shí)本文會(huì)對(duì) Python 的一些用法與 JS 進(jìn)行類(lèi)比。不管是提升自己的知識(shí)廣度奴紧,還是更好地迎接 AI 時(shí)代特姐,Python 都是一門(mén)值得學(xué)習(xí)的語(yǔ)言。
Python學(xué)習(xí)資料或者需要代碼黍氮、視頻加Python學(xué)習(xí)群:960410445
數(shù)據(jù)類(lèi)型
在 Python 中唐含,最常用的能夠直接處理的數(shù)據(jù)類(lèi)型有以下幾種:
數(shù)字[整數(shù)(int)、浮點(diǎn)型(float)沫浆、長(zhǎng)整型(long)捷枯、復(fù)數(shù)(complex)]
字符串(str)
布爾值(bool)
空值(None)
除此之外,Python 還提供了列表[list]专执、字典[dict] 等多種數(shù)據(jù)類(lèi)型淮捆,這在下文中會(huì)介紹。
類(lèi)型轉(zhuǎn)換與類(lèi)型判斷
與 JS 十分類(lèi)似他炊,python 也能實(shí)現(xiàn)不同數(shù)據(jù)類(lèi)型間的強(qiáng)制與隱式轉(zhuǎn)換争剿,例子如下:
強(qiáng)制類(lèi)型轉(zhuǎn)換:
隱式類(lèi)型轉(zhuǎn)換:
此外寫(xiě)代碼的時(shí)候經(jīng)常會(huì)需要判斷值的類(lèi)型,可以 使用 python 提供的 type() 函數(shù)獲取變量的類(lèi)型痊末,或者使用 isinstance(x, type) 來(lái)判斷 x 是否屬于相應(yīng)的 type 類(lèi)型蚕苇。
有序集合類(lèi)型
集合是指包含一組元素的數(shù)據(jù)結(jié)構(gòu),有序集合即集合里面的元素是是按照順序排列的凿叠,Python 中的有序集合大概有以下幾類(lèi):list, tuple, str, unicode涩笤。
list 類(lèi)型
Python 中 List 類(lèi)型類(lèi)似于 JS 中的 Array,
tuple 類(lèi)型
tuple 類(lèi)型是另一種有序的列表,中文翻譯為" 元組 "蹬碧。tuple 和 list 非常類(lèi)似舱禽,但是,tuple 一旦創(chuàng)建完畢恩沽,就不能修改了誊稚。
無(wú)序集合類(lèi)型
dict 類(lèi)型
Python 中的 dict 類(lèi)型類(lèi)似于 JS 中的 {} (最大的不同是它是沒(méi)有順序的), 它有如下特點(diǎn):
查找速度快 (無(wú)論 dict 有 10 個(gè)元素還是 10 萬(wàn)個(gè)元素,查找速度都一樣)
占用內(nèi)存大 (與 list 類(lèi)型相反)
dict 中的 key 不能重復(fù)
dict 中存儲(chǔ)的 key-value 序?qū)κ菦](méi)有順序的
set 類(lèi)型
有的時(shí)候罗心,我們只想要 dict 的 key里伯,不關(guān)心 key 對(duì)應(yīng)的 value,而且要保證這個(gè)集合的元素不會(huì)重復(fù)渤闷,這時(shí)疾瓮,set 類(lèi)型就派上用場(chǎng)了。set 類(lèi)型有如下特點(diǎn):
set 存儲(chǔ)的元素和 dict 的 key 類(lèi)似飒箭,必須是不變對(duì)象
set 存儲(chǔ)的元素也是沒(méi)有順序的
Python 中的迭代
在介紹完 Python 中的有序集合和無(wú)序集合類(lèi)型后狼电,必然存在遍歷集合的 for 循環(huán)。但是和其它語(yǔ)言的標(biāo)準(zhǔn) for 循環(huán)不同弦蹂,Python 中的所有迭代是通過(guò) for ... in 來(lái)完成的肩碟。以下給出一些常用的迭代 demos:
索引迭代:
迭代 dict 的 value:
迭代 dict 的 key 和 value:
切片操作符
Python 提供的切片操作符類(lèi)似于 JS 提供的原生函數(shù) slice()。有了切片操作符盈匾,大大簡(jiǎn)化了一些原來(lái)得用循環(huán)的操作腾务。
列表生成器
如果要生成 [1x1, 2x2, 3x3, ..., 10x10] 怎么做?方法一是循環(huán):
但是循環(huán)太繁瑣削饵,而列表生成式則可以用一行語(yǔ)句代替循環(huán)生成上面的 list:
列表生成式的 for 循環(huán)后面還可以加上 if 判斷(類(lèi)似于 JS 中的 filter() 函數(shù))岩瘦,示例如下:
for 循環(huán)可以嵌套,因此窿撬,在列表生成式中启昧,也可以用多層 for 循環(huán)來(lái)生成列表。
Python 函數(shù)
默認(rèn)參數(shù)
JS 中 ES6 的 默認(rèn)參數(shù)正是借鑒于 Python劈伴,用法如下:
可變參數(shù)
類(lèi)似于 JS 函數(shù)中自動(dòng)識(shí)別傳入?yún)?shù)的個(gè)數(shù)密末,Python 也提供了定義可變參數(shù),即在可變參數(shù)的名字前面帶上個(gè) * 號(hào)跛璧。
Python 解釋器會(huì)把傳入的一組參數(shù)組裝成一個(gè) tuple 傳遞給可變參數(shù)严里,因此,在函數(shù)內(nèi)部追城,直接把變量 args 看成一個(gè) tuple 就好了刹碾。
常用高階函數(shù)
Python 中常用的函數(shù) (map、reduce座柱、filter) 的作用和 JS 中一致迷帜,只是用法稍微不同物舒。
map 函數(shù): 接收一個(gè)函數(shù) f 和一個(gè) list,并通過(guò)把函數(shù) f 依次作用在 list 的每個(gè)元素上戏锹,得到一個(gè)新的 list 并返回冠胯。
reduce 函數(shù): 接收一個(gè)函數(shù) f 和一個(gè) list(可以接受第三個(gè)值作為初始值),reduce() 對(duì) list 的每個(gè)元素反復(fù)調(diào)用函數(shù) f锦针,并返回最終結(jié)果值荠察。
filter 函數(shù): 接收一個(gè)函數(shù) f 和一個(gè)list,這個(gè)函數(shù) f 的作用是對(duì)每個(gè)元素進(jìn)行判斷奈搜,返回 True或 False割粮,filter() 根據(jù)判斷結(jié)果自動(dòng)過(guò)濾掉不符合條件的元素,返回由符合條件元素組成的新 list媚污。
匿名函數(shù)
和 JS 的匿名函數(shù)不同的地方是,Python 的匿名函數(shù)中只能有一個(gè)表達(dá)式廷雅,且不能寫(xiě) return耗美。拿 map() 函數(shù)為例:
map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]) # [1, 4, 9, 16, 25, 36, 49, 64, 81]
關(guān)鍵詞 lambda 表示匿名函數(shù),冒號(hào)前面的 x 表示函數(shù)參數(shù)航缀,可以看出匿名函數(shù) lambda x: x* x實(shí)際上就是:
def f(x):
return x * x
閉包
之前寫(xiě)過(guò)一些關(guān)于 JS 閉包的文章商架,比如 深入淺出JavaScript之閉包(Closure)、以及 讀書(shū)筆記-你不知道的 JavaScript (上)芥玉,Python 中閉包的定義和 JS 中的是一致的即:內(nèi)層函數(shù)引用了外層函數(shù)的變量蛇摸,然后返回內(nèi)層函數(shù)。下面來(lái)看下 Py 中閉包之 for 循環(huán)經(jīng)典問(wèn)題:
老問(wèn)題了灿巧,f1(), f2(), f3() 結(jié)果不應(yīng)該是 1, 4, 9 嗎赶袄,實(shí)際結(jié)果為什么都是 9 呢?
原因就是當(dāng) count() 函數(shù)返回了 3 個(gè)函數(shù)時(shí)抠藕,這 3 個(gè)函數(shù)所引用的變量 i 的值已經(jīng)變成了 3饿肺。由于 f1、f2盾似、f3 并沒(méi)有被調(diào)用敬辣,所以,此時(shí)他們并未計(jì)算 i*i零院,當(dāng) f1 被調(diào)用時(shí)溉跃,i 已經(jīng)變?yōu)?3 了。
要正確使用閉包告抄,就要確保引用的局部變量在函數(shù)返回后不能變撰茎。代碼修改如下:
方法一:?可以理解為創(chuàng)建了一個(gè)封閉的作用域,i 的 值傳給 j 之后玄妈,就和 i 沒(méi)任何關(guān)系了乾吻。每次循環(huán)形成的閉包都存進(jìn)了內(nèi)存中髓梅。
方法二:思路比較巧妙,用到了默認(rèn)參數(shù) j 在函數(shù)定義時(shí)可以獲取到 i 的值绎签,雖然沒(méi)有用到閉包枯饿,但是和方法一有異曲同工之處。
decorator 裝飾器
ES6 的語(yǔ)法中的 decorator 正是借鑒了 Python 的 decorator诡必。decorator 本質(zhì)上就是 一個(gè)高階函數(shù)奢方,它接收一個(gè)函數(shù)作為參數(shù),然后返回一個(gè)新函數(shù)爸舒。
那裝飾器的作用在哪呢蟋字?先上一段日常項(xiàng)目中用 ts 寫(xiě)的網(wǎng)關(guān)代碼:
可以看出使用裝飾器可以極大地簡(jiǎn)化代碼,避免每個(gè)函數(shù)(比如日志扭勉、路由鹊奖、性能檢測(cè))編寫(xiě)重復(fù)性代碼。
回到 Python 上涂炎,Python 提供的 @ 語(yǔ)法來(lái)使用 decorator忠聚, @ 等價(jià)于 f = decorate(f)。下面來(lái)看看 @log() 在 Python 中的實(shí)現(xiàn):
class
面向?qū)ο缶幊?/p>
面向?qū)ο缶幊淌且环N程序設(shè)計(jì)范式唱捣,基本思想是:用類(lèi)定義抽象類(lèi)型两蟀,然后根據(jù)類(lèi)的定義創(chuàng)建出實(shí)例。在掌握其它語(yǔ)言的基礎(chǔ)上震缭,還是比較容易理解這塊知識(shí)點(diǎn)的赂毯,比如從下面兩種寫(xiě)法可以看出不同語(yǔ)言的語(yǔ)言特性間竟然有如此多的共性。
es6: (附:本文的主題是 python拣宰,所以只是初略展示下 js 中類(lèi)的定義以及實(shí)例的創(chuàng)建党涕,為了說(shuō)明寫(xiě)法的相似性)
Python: (核心要點(diǎn)寫(xiě)在注釋中)
繼承
child 屬于 Student 類(lèi),Student 類(lèi)屬于 People 類(lèi)徐裸,這就引出了繼承: 即獲得了父類(lèi)的方法屬性后又能添加自己的方法屬性遣鼓。
可以看到子類(lèi)在父類(lèi)的基礎(chǔ)上又增加了 grade 屬性。我們可以再來(lái)看看 s 的類(lèi)型重贺。
可以看出骑祟,Python 中在一條繼承鏈上,一個(gè)實(shí)例可以看成它本身的類(lèi)型气笙,也可以看成它父類(lèi)的類(lèi)型次企。