在這個(gè)例子中我們用到了一種特殊的函數(shù):lambda表達(dá)式。Lambda表達(dá)式在Python中是一種匿名函數(shù),lambda關(guān)鍵字后面跟輸入?yún)?shù),然后冒號(hào)后面是返回值(的表達(dá)式),比如上邊例子中就是一個(gè)取下標(biāo)1元素的函數(shù)。當(dāng)然,還是那句話,萬(wàn)物皆對(duì)象,給lambda表達(dá)式取名字也是一點(diǎn)問(wèn)題沒(méi)有的:
some_ops = lambda x, y: x + y + x*y + x**y
some_ops(2, 3) # 2 + 3 + 2*3 + 2^3 = 19
生成器(Generator)
生成器是迭代器的一種,形式上看和函數(shù)很像,只是把return換成了yield,在每次調(diào)用的時(shí)候,都會(huì)執(zhí)行到y(tǒng)ield并返回值,同時(shí)將當(dāng)前狀態(tài)保存,等待下次執(zhí)行到y(tǒng)ield再繼續(xù):
# 從10倒數(shù)到0
def countdown(x):
while x >= 0:
yield x
x -= 1
for i in countdown(10):
print(i)
# 打印小于100的斐波那契數(shù)
def fibonacci(n):
a = 0
b = 1
while b < n:
yield b
a, b = b, a + b
for x in fibonacci(100):
print(x)
生成器和所有可迭代結(jié)構(gòu)一樣,可以通過(guò)next()函數(shù)返回下一個(gè)值,如果迭代結(jié)束了則拋出StopIteration異常:
a = fibonacci(3)
print(next(a)) # 1
print(next(a)) # 1
print(next(a)) # 2
print(next(a)) # 拋出StopIteration異常
Python3.3以上可以允許yield和return同時(shí)使用,return的是異常的說(shuō)明信息:
# Python3.3以上可以return返回異常的說(shuō)明
def another_fibonacci(n):
a = 0
b = 1
while b < n:
yield b
a, b = b, a + b
return "No more ..."
a = another_fibonacci(3)
print(next(a)) # 1
print(next(a)) # 1
print(next(a)) # 2
print(next(a)) # 拋出StopIteration異常并打印No more消息
類(Class)
Python中的類的概念和其他語(yǔ)言相比沒(méi)什么不同,比較特殊的是protected和private在Python中是沒(méi)有明確限制的,一個(gè)慣例是用單下劃線開(kāi)頭的表示protected,用雙下劃線開(kāi)頭的表示private:
class A:
"""Class A"""
def __init__(self, x, y, name):
self.x = x
self.y = y
self._name = name
def introduce(self):
print(self._name)
def greeting(self):
print("What's up!")
def __l2norm(self):
return self.x**2 + self.y**2
def cal_l2norm(self):
return self.__l2norm()
a = A(11, 11, 'Leonardo')
print(A.__doc__) # "Class A"
a.introduce() # "Leonardo"
a.greeting() # "What's up!"
print(a._name) # 可以正常訪問(wèn)
print(a.cal_l2norm()) # 輸出11*11+11*11=242
print(a._A__l2norm()) # 仍然可以訪問(wèn),只是名字不一樣
print(a.__l2norm()) # 報(bào)錯(cuò): 'A' object has no attribute '__l2norm'
類的初始化使用的是__init__(self,),所有成員變量都是self的,所以以self.開(kāi)頭。可以看到,單下劃線開(kāi)頭的變量是可以直接訪問(wèn)的,而雙下劃線開(kāi)頭的變量則觸發(fā)了Python中一種叫做name mangling的機(jī)制,其實(shí)就是名字變了下,仍然可以通過(guò)前邊加上“_類名”的方式訪問(wèn)。也就是說(shuō)Python中變量的訪問(wèn)權(quán)限都是靠自覺(jué)的。類定義中緊跟著類名字下一行的字符串叫做docstring,可以寫(xiě)一些用于描述類的介紹,如果有定義則通過(guò)“類名.__doc__”訪問(wèn)。這種前后都加雙下劃線訪問(wèn)的是特殊的變量/方法,除了__doc__和__init__還有很多,這里就不展開(kāi)講了。
Python中的繼承也非常簡(jiǎn)單,最基本的繼承方式就是定義類的時(shí)候把父類往括號(hào)里一放就行了:
class B(A):
"""Class B inheritenced from A"""
def greeting(self):
print("How's going!")
b = B(12, 12, 'Flaubert')
b.introduce() # Flaubert
b.greeting() # How's going!
print(b._name()) # Flaubert
print(b._A__l2norm()) # “私有”方法,必須通過(guò)_A__l2norm訪問(wèn)
map, reduce和filter
map可以用于對(duì)可遍歷結(jié)構(gòu)的每個(gè)元素執(zhí)行同樣的操作,批量操作:
map(lambda x: x**2, [1, 2, 3, 4]) # [1, 4, 9, 16]
map(lambda x, y: x + y, [1, 2, 3], [5, 6, 7]) # [6, 8, 10]
reduce則是對(duì)可遍歷結(jié)構(gòu)的元素按順序進(jìn)行兩個(gè)輸入?yún)?shù)的操作,并且每次的結(jié)果保存作為下次操作的第一個(gè)輸入?yún)?shù),還沒(méi)有遍歷的元素作為第二個(gè)輸入?yún)?shù)。這樣的結(jié)果就是把一串可遍歷的值,減少(reduce)成一個(gè)對(duì)象:
reduce(lambda x, y: x + y, [1, 2, 3, 4]) # ((1+2)+3)+4=10
filter顧名思義,根據(jù)條件對(duì)可遍歷結(jié)構(gòu)進(jìn)行篩選:
filter(lambda x: x % 2, [1, 2, 3, 4, 5]) # 篩選奇數(shù),[1, 3, 5]
需要注意的是,對(duì)于filter和map,在Python2中返回結(jié)果是列表,Python3中是生成器。
列表生成(list comprehension)
列表生成是Python2.0中加入的一種語(yǔ)法,可以非常方便地用來(lái)生成列表和迭代器,比如上節(jié)中map的兩個(gè)例子和filter的一個(gè)例子可以用列表生成重寫(xiě)為:
[x**2 for x in [1, 2, 3, 4]] # [1, 4, 9 16]
[sum(x) for x in zip([1, 2, 3], [5, 6, 7])] # [6, 8, 10]
[x for x in [1, 2, 3, 4, 5] if x % 2] # [1, 3, 5]
評(píng)論
查看更多