摘要:作為一名前端開發(fā)者,也了解中的很多特性借鑒自比如默認(rèn)參數(shù)解構(gòu)賦值等,同時本文會對的一些用法與進(jìn)行類比。函數(shù)接收一個函數(shù)和一個,這個函數(shù)的作用是對每個元素進(jìn)行判斷,返回或,根據(jù)判斷結(jié)果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新。
本文首發(fā)在 個人博客
Python 是一門運用很廣泛的語言,自動化腳本、爬蟲,甚至在深度學(xué)習(xí)領(lǐng)域也都有 Python 的身影。作為一名前端開發(fā)者,也了解 ES6 中的很多特性借鑒自 Python (比如默認(rèn)參數(shù)、解構(gòu)賦值、Decorator等),同時本文會對 Python 的一些用法與 JS 進(jìn)行類比。不管是提升自己的知識廣度,還是更好地迎接 AI 時代,Python 都是一門值得學(xué)習(xí)的語言。
數(shù)據(jù)類型在 Python 中,最常用的能夠直接處理的數(shù)據(jù)類型有以下幾種:
數(shù)字[整數(shù)(int)、浮點型(float)、長整型(long)、復(fù)數(shù)(complex)]
字符串(str)
布爾值(bool)
空值(None)
除此之外,Python 還提供了列表[list]、字典[dict] 等多種數(shù)據(jù)類型,這在下文中會介紹。
類型轉(zhuǎn)換與類型判斷與 JS 十分類似,python 也能實現(xiàn)不同數(shù)據(jù)類型間的強(qiáng)制與隱式轉(zhuǎn)換,例子如下:
強(qiáng)制類型轉(zhuǎn)換:
int("3") # 3 str(3.14) # "3.14" float("3.14") # 3.14 # 區(qū)別于 JS 只有 Number 一種類型,Python 中數(shù)字中的不同類型也能相互強(qiáng)制轉(zhuǎn)換 float(3) # 3.0 bool(3) # True bool(0) # False
隱式類型轉(zhuǎn)換:
1 + 1.0 # 2.0 1 + False # 1 1.0 + True # 2.0 # 區(qū)別于 JS 的 String + Number = String, py 中 str + int 會報錯 1 + "1" # TypeError: cannot concatenate "str" and "int" objects
此外寫代碼的時候經(jīng)常會需要判斷值的類型,可以 使用 python 提供的 type() 函數(shù)獲取變量的類型,或者使用 isinstance(x, type) 來判斷 x 是否屬于相應(yīng)的 type 類型。
type(1.3) == float # True isinstance("a", str) # True isinstance(1.3, int) # False isinstance(True, bool) # True isinstance([], list) # True isinstance({}, dict) # True有序集合類型
集合是指包含一組元素的數(shù)據(jù)結(jié)構(gòu),有序集合即集合里面的元素是是按照順序排列的,Python 中的有序集合大概有以下幾類:list, tuple, str, unicode。
list 類型Python 中 List 類型類似于 JS 中的 Array,
L = [1, 2, 3] print L[-1] # "3" L.append(4) # 末尾添加元素 print L # [1, 2, 3, 4] L.insert(0, "hi") # 指定索引位置添加元素 print L # ["hi", 1, 2, 3, 4] L.pop() # 末尾移除元素 L.pop(2) ?????? 2 ??? print L # ["hi", 1, 2, 3]tuple 類型
tuple 類型是另一種有序的列表,中文翻譯為“ 元組 ”。tuple 和 list 非常類似,但是,tuple 一旦創(chuàng)建完畢,就不能修改了。
t = (1, 2, 3) print t[0] # 1 t[0] = 11 # TypeError: "tuple" object does not support item assignment t = (1) print t # 1 t 的結(jié)果是整數(shù) 1 t = (1,) # 為了避免出現(xiàn)如上有歧義的單元素 tuple,所以 Python 規(guī)定,單元素 tuple 要多加一個逗號“,” print t # (1,)無序集合類型 dict 類型
Python 中的 dict 類型類似于 JS 中的 {} (最大的不同是它是沒有順序的), 它有如下特點:
查找速度快 (無論 dict 有 10 個元素還是 10 萬個元素,查找速度都一樣)
占用內(nèi)存大 (與 list 類型相反)
dict 中的 key 不能重復(fù)
dict 中存儲的 key-value 序?qū)κ菦]有順序的
d = { "a": 1, "b": 2, "c": 3 } print d # {"a": 1, "c": 3, "b": 2} 可以看出打印出的序?qū)]有按正常的順序打出 # 遍歷 dict for key,value in d.items(): print("%s: %s" % (key,value)) # a: 1 # c: 3 # b: 2set 類型
有的時候,我們只想要 dict 的 key,不關(guān)心 key 對應(yīng)的 value,而且要保證這個集合的元素不會重復(fù),這時,set 類型就派上用場了。set 類型有如下特點:
set 存儲的元素和 dict 的 key 類似,必須是不變對象
set 存儲的元素也是沒有順序的
s = set(["A", "B", "C", "C"]) print s # set(["A", "C", "B"]) s.add("D") print s # set(["A", "C", "B", "D"]) s.remove("D") print s # set(["A", "C", "B"])Python 中的迭代
在介紹完 Python 中的有序集合和無序集合類型后,必然存在遍歷集合的 for 循環(huán)。但是和其它語言的標(biāo)準(zhǔn) for 循環(huán)不同,Python 中的所有迭代是通過 for ... in 來完成的。以下給出一些常用的迭代 demos:
索引迭代:
L = ["apple", "banana", "orange"] for index, name in enumerate(L): # enumerate() 函數(shù)把 ["apple", "banana", "orange"] 變成了類似 [(0, "apple), (1, "banana"), (2, "orange")] 的形式 print index, "-", name # 0 - apple # 1 - banana # 2 - orange
迭代 dict 的 value:
d = { "apple": 6, "banana": 8, "orange": 5 } print d.values() # [6, 8, 5] for v in d.values() print v # 6 # 8 # 5
迭代 dict 的 key 和 value:
d = { "apple": 6, "banana": 8, "orange": 5 } for key, value in d.items() print key, ":", value # apple : 6 # banana: 8 # orange: 5切片操作符
Python 提供的切片操作符類似于 JS 提供的原生函數(shù) slice()。有了切片操作符,大大簡化了一些原來得用循環(huán)的操作。
L = ["apple", "banana", "orange", "pear"] L[0:2] # ["apple", "banana"] 取前 2 個元素 L[:2] # ["apple", "banana"] 如果第一個索引是 0,可以省略 L[:] # ["apple", "banana", "orange", "pear"] 只用一個 : ,表示從頭到尾 L[::2] # ["apple", "orange"] 第三個參數(shù)表示每 N 個取一個,這里表示從頭開始,每 2 個元素取出一個來列表生成器
如果要生成 [1x1, 2x2, 3x3, ..., 10x10] 怎么做?方法一是循環(huán):
L = [] for x in range(1, 11): L.append(x * x)
但是循環(huán)太繁瑣,而列表生成式則可以用一行語句代替循環(huán)生成上面的 list:
# 把要生成的元素 x * x 放到前面,后面跟 for 循環(huán),就可以把 list 創(chuàng)建出來 [x * x for x in range(1, 11)] # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
列表生成式的 for 循環(huán)后面還可以加上 if 判斷(類似于 JS 中的 filter() 函數(shù)),示例如下:
[x * x for x in range(1, 11) if x % 2 == 0] # [4, 16, 36, 64, 100]
for 循環(huán)可以嵌套,因此,在列表生成式中,也可以用多層 for 循環(huán)來生成列表。
[m + n for m in "ABC" for n in "123"] # ["A1", "A2", "A3", "B1", "B2", "B3", "C1", "C2", "C3"]Python 函數(shù) 默認(rèn)參數(shù)
JS 中 ES6 的 默認(rèn)參數(shù)正是借鑒于 Python,用法如下:
def greet(name="World"): print "Hello, " + name + "." greet() # Hello, World. greet("Python") # Hello, Python.可變參數(shù)
類似于 JS 函數(shù)中自動識別傳入?yún)?shù)的個數(shù),Python 也提供了定義可變參數(shù),即在可變參數(shù)的名字前面帶上個 * 號。
def fn(*args): print args fn() # () fn("a") # ("a",) fn("a", "b") # ("a", "b")
Python 解釋器會把傳入的一組參數(shù)組裝成一個 tuple 傳遞給可變參數(shù),因此,在函數(shù)內(nèi)部,直接把變量 args 看成一個 tuple 就好了。
常用高階函數(shù)Python 中常用的函數(shù) (map、reduce、filter) 的作用和 JS 中一致,只是用法稍微不同。
map 函數(shù): 接收一個函數(shù) f 和一個 list,并通過把函數(shù) f 依次作用在 list 的每個元素上,得到一個新的 list 并返回。
def f(x): return x * x print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) # [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce 函數(shù): 接收一個函數(shù) f 和一個 list(可以接受第三個值作為初始值),reduce() 對 list 的每個元素反復(fù)調(diào)用函數(shù) f,并返回最終結(jié)果值。
def f(x, y): return x * y reduce(f, [1, 3, 5]) # 15
filter 函數(shù): 接收一個函數(shù) f 和一個list,這個函數(shù) f 的作用是對每個元素進(jìn)行判斷,返回 True或 False,filter() 根據(jù)判斷結(jié)果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新 list。
def is_odd(x): return x % 2 == 1 filter(is_odd, [1, 4, 6, 7, 9, 12, 17]) # [1, 7, 9, 17]匿名函數(shù)
和 JS 的匿名函數(shù)不同的地方是,Python 的匿名函數(shù)中只能有一個表達(dá)式,且不能寫 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ù),冒號前面的 x 表示函數(shù)參數(shù),可以看出匿名函數(shù) lambda x: x* x 實際上就是:
def f(x): return x * x閉包
之前寫過一些關(guān)于 JS 閉包的文章,比如 深入淺出JavaScript之閉包(Closure)、以及 讀書筆記-你不知道的 JavaScript (上),Python 中閉包的定義和 JS 中的是一致的即:內(nèi)層函數(shù)引用了外層函數(shù)的變量,然后返回內(nèi)層函數(shù)。下面來看下 Py 中閉包之 for 循環(huán)經(jīng)典問題:
# 希望一次返回3個函數(shù),分別計算1x1,2x2,3x3: def count(): fs = [] for i in range(1, 4): def f(): return i * i fs.append(f) return fs f1, f2, f3 = count() # 這種寫法相當(dāng)于 ES6 中的解構(gòu)賦值 print f1(), f2(), f3() # 9 9 9
老問題了,f1(), f2(), f3() 結(jié)果不應(yīng)該是 1, 4, 9 嗎,實際結(jié)果為什么都是 9 呢?
原因就是當(dāng) count() 函數(shù)返回了 3 個函數(shù)時,這 3 個函數(shù)所引用的變量 i 的值已經(jīng)變成了 3。由于 f1、f2、f3 并沒有被調(diào)用,所以,此時他們并未計算 i*i,當(dāng) f1 被調(diào)用時,i 已經(jīng)變?yōu)?3 了。
要正確使用閉包,就要確保引用的局部變量在函數(shù)返回后不能變。代碼修改如下:
方法一: 可以理解為創(chuàng)建了一個封閉的作用域,i 的 值傳給 j 之后,就和 i 沒任何關(guān)系了。每次循環(huán)形成的閉包都存進(jìn)了內(nèi)存中。
def count(): fs = [] for i in range(1, 4): def f(j): def g(): # 方法一 return j * j return g r = f(i) fs.append(r) return fs f1, f2, f3 = count() print f1(), f2(), f3() # 1 4 9
方法二:思路比較巧妙,用到了默認(rèn)參數(shù) j 在函數(shù)定義時可以獲取到 i 的值,雖然沒有用到閉包,但是和方法一有異曲同工之處。
def count(): fs = [] for i in range(1, 4): def f(j = i): # 方法二 return j * j fs.append(f) return fs f1, f2, f3 = count() print f1(), f2(), f3() # 1 4 9decorator 裝飾器
ES6 的語法中的 decorator 正是借鑒了 Python 的 decorator。decorator 本質(zhì)上就是一個高階函數(shù),它接收一個函數(shù)作為參數(shù),然后返回一個新函數(shù)。
那裝飾器的作用在哪呢?先上一段日常項目中用 ts 寫的網(wǎng)關(guān)代碼:
@Post("/rider/detail") // URL 路由 @log() // 打印日志 @ResponseBody public async getRiderBasicInfo( @RequestBody("riderId") riderId: number, @RequestBody("cityId") cityId: number, ) { const result = await this.riderManager.findDetail(cityId, riderId) return result }
可以看出使用裝飾器可以極大地簡化代碼,避免每個函數(shù)(比如日志、路由、性能檢測)編寫重復(fù)性代碼。
回到 Python 上,Python 提供的 @ 語法來使用 decorator,@ 等價于 f = decorate(f)。下面來看看 @log() 在 Python 中的實現(xiàn):
# 我們想把調(diào)用的函數(shù)名字給打印出來 @log() def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10) # 來看看 @log() 的定義 def log(): def log_decorator(f): def fn(x): print "調(diào)用了函數(shù)" + f.__name__ + "()" return f(x) return fn return log_decorator # 結(jié)果 # 調(diào)用了函數(shù) factorial() # 3628800class 面向?qū)ο缶幊?/b>
面向?qū)ο缶幊淌且环N程序設(shè)計范式,基本思想是:用類定義抽象類型,然后根據(jù)類的定義創(chuàng)建出實例。在掌握其它語言的基礎(chǔ)上,還是比較容易理解這塊知識點的,比如從下面兩種寫法可以看出不同語言的語言特性間竟然有如此多的共性。
es6: (附:本文的主題是 python,所以只是初略展示下 js 中類的定義以及實例的創(chuàng)建,為了說明寫法的相似性)
class Person { constructor(name, age) { this.name = name this.age = age } } const child1 = new Person("Xiao Ming", 10)
Python: (核心要點寫在注釋中)
# 定義一個 Person 類:根據(jù) Person 類就可以造成很多 child 實例 class Person(object): address = "Earth" # 類屬性 (實例公有) def __init__(self, name, age): # 創(chuàng)建實例時,__init__()方法被自動調(diào)用 self.name = name self.age = age def get_age(self): # 定義實例方法,它的第一個參數(shù)永遠(yuǎn)是 self,指向調(diào)用該方法的實例本身,其他參數(shù)和普通函數(shù)是一樣的 return self.age child1 = Person("Xiao Ming", 10) child2 = Person("Xiao Hong", 9) print child1.name # "Xiao Ming" print child2.get_age() # 9 print child1.address # "Earth" print child2.address # "Earth"繼承
child 屬于 Student 類,Student 類屬于 People 類,這就引出了繼承: 即獲得了父類的方法屬性后又能添加自己的方法屬性。
class Person(object): def __init__(self, name, age): self.name = name self.age = age class Student(Person): def __init__(self, name, age, grade): super(Student, self).__init__(name, age) # 這里也能寫出 Person.__init__(self, name, age) self.grade = grade s = Student("Xiao Ming", 10, 90) print s.name # "Xiao Ming" print s.grade # 90
可以看到子類在父類的基礎(chǔ)上又增加了 grade 屬性。我們可以再來看看 s 的類型。
isinstance(s, Person) isinstance(s, Student)
可以看出,Python 中在一條繼承鏈上,一個實例可以看成它本身的類型,也可以看成它父類的類型。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/40987.html
摘要:正則學(xué)起來說真的,不去正兒八經(jīng)的學(xué)正則,對付一般的工作是沒啥問題的,雖然我們可能會經(jīng)常用到,但畢竟度娘能提供大多時候你想要的可當(dāng)我看一些框架的源碼,總會被里面一長串一長串的正則給嚇到之前一篇博客里有關(guān)于簡單的爬蟲實踐,其實離達(dá)到我預(yù)期的效果 正則學(xué)起來 說真的,不去正兒八經(jīng)的學(xué)正則,對付一般的工作是沒啥問題的,雖然我們可能會經(jīng)常用到replace,但畢竟度娘能提供大多時候你想要的;可當(dāng)...
摘要:小白看過來讓爬蟲成為你的好幫手隨著信息化社會的到來,人們對網(wǎng)絡(luò)爬蟲這個詞已經(jīng)不再陌生。互動活動關(guān)于華為云微認(rèn)證的任何問題,均可在下方評論區(qū)留言。華為云微認(rèn)證每期將送出個免費機(jī)會,獎項公布時間月日。 小白看過來 讓Python爬蟲成為你的好幫手 隨著信息化社會的到來,人們對網(wǎng)絡(luò)爬蟲這個詞已經(jīng)不再陌生。但什么是爬蟲,如何利用爬蟲為自己服務(wù),這聽起來有些高大上。下面一文帶你走近爬蟲世界,讓即...
摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書清單,以付費的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個友善的吐槽讀書清單也要收費。這本書便從的異步編程講起,幫助我們設(shè)計快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡單的頁面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書清單,以付費的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費分享到這里,不足之處歡迎指教...
摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書清單,以付費的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個友善的吐槽讀書清單也要收費。這本書便從的異步編程講起,幫助我們設(shè)計快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡單的頁面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書清單,以付費的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費分享到這里,不足之處歡迎指教...
閱讀 2556·2021-09-22 15:25
閱讀 2963·2021-09-14 18:03
閱讀 1212·2021-09-09 09:33
閱讀 1700·2021-09-07 09:59
閱讀 2930·2021-07-29 13:50
閱讀 1500·2019-08-30 15:44
閱讀 1715·2019-08-29 16:22
閱讀 1287·2019-08-29 12:49