Python筆記 (二) 進階

進階語法

with ... as 上下文管理協議

with 語句適用于對資源進行訪問的場合,確保不管使用過程中是否發生異常都會執行必要的“清理”操作,釋放資源,比如文件使用后自動關閉、線程中鎖的自動獲取和釋放等。

已經加入對上下文管理協議支持的還有模塊 threading、decimal 等。

# 操作文件
with open('file.txt') as f:
    for line in f:
        print(line)

匿名函數lambda

在python中使用lambda來創建匿名函數,在需要傳遞函數作為參數的地方使用lambda更方便。

一個lambda的例子

list(map(lambda x: x*x, [1,2,3,4,5]))  #[1, 4, 9, 16, 25]

# lambdx x: x*x 等于下面的f函數  可以直接f = lambda x: x*x 賦值后調用
def f(x):
    return x*x
list(map(f,[1,2,3,4,5]))

對象模擬函數 可調用接口

對象通過__call__(self [, *args [, **kwargs]])方法模擬函數行為。如果一個對象x提供了該方法,就可以像函數一樣調用它。

class DistanceFrom(object):
    def __init__(self,origin):
        self.origin = origin
    def __call__(self,x):
        return abs(x-self.origin)
        
nums = [1,37,42,101,13,9,-20]
newnums = sorted(nums,key=DistanceFrom(10))  #按照與10的距離排序

以上效果等同于

newnums = sorted(nums,lambda x:abs(x-10))

當然也可以直接把DistanceFrom定義成函數

使用閉包

將組成函數的語句和這些語句的執行環境打包在一起時,得到的對象稱為閉包

# 計數器測試閉包效率,和使用類的時候對比
import timeit
def count(x):
    def next():
        nonlocal x
        n = x
        x -= 1
        return n
    return next

class count2:
    def __init__(self,x):
        self.x = x
    def next(self):
        n = self.x
        self.x -= 1
        return n
    
def test():
    next = count(1000000)
    while 1:
        v = next()
        if not v:break

def test2():
    c = count2(1000000)
    while 1:
        v = c.next()
        if not v:break
        
t2 = timeit.timeit(test2,number=10)
print(t2)
t = timeit.timeit(test,number=10)
print(t)

# 輸出結果,閉包效率大概是正常方法的2倍
# 4.5261534636385345
# 2.468003824508422

裝飾器

裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數對象。它經常用于有切面需求的場景,比如:插入日志、性能測試、事務處理、緩存、權限校驗等場景。

參考知乎:如何理解Python裝飾器?

@wraps(func)裝飾裝飾函數,能把原函數的元信息拷貝到裝飾器函數中。

上面閉包性能測試改成使用裝飾器測試性能

import timeit

def timeit_test(number):
    def decorated(func):
        print(timeit.timeit(func,number=number))
        return func
    return decorated

    '''略'''
    '''略'''

@timeit_test(number=10)
def test():
    next = count(1000000)
    while 1:
        v = next()
        if not v:break
        
@timeit_test(number=10)
def test2():
    c = count2(1000000)
    while 1:
        v = c.next()
        if not v:break
# 裝飾器中已運行測試方法,不需要再主動運行

yield和生成器

盡量使用生成器
range(num) ----> xrange(nums) #僅限python2,python3中range就等于之前的xrange
for k,v in dict.items() ----> for k,v in dict.iteritems()
for k in dict.keys() ----> for k in iterkeys()

yied生成斐波那契數列

def fab(max):
    n ,a, b = 0, 0 ,1
    while n < max:
        print('before fab %d' %n)
        yield a
        print('after fab %d' %n)
        a, b = b, a + b
        n += 1

for n in fab(5):
    print(n)
# 迭代就是重復運行__next__()
print('//////////////////////////////////////////')
c = fab(5)
print(c.__next__())
print(c.__next__())
print(c.__next__())
print(c.__next__())
print(c.__next__())

for循環迭代fab(5)等同于

c = fab(5)
print(c.__next__())   #運行5次

注意運行結果,每循環一次其實代碼只執行到yield那一行,下一次循環直接從yield后面的代碼開始執行到下一次調用yield

Paste_Image.png

yield和協程

def fab():
    a, b, n = 0, 1 ,0
    fablist = []
    while True:
        number = yield fablist  # 返回值不是必須的,如果number = yield,則返回的是None
        while n < number:
            n += 1
            fablist.append(a)
            a, b = b ,a + b

c = fab()
c.__next__()
for i in range(3,7):
    print(c.send(i*10))

next()的初始調用是必須的,yield語句那里協程會掛起,等待相關生成器對象c的send()方法給它發送一個值。
可以定義一個coroutine裝飾器改寫上述語句,這看起來和tornado以及asyncio很相似了。

def coroutine(func):
    def start(*args, **kwargs):
        c = func(*args, **kwargs)
        c.__next__()
        return c
    return start


@coroutine
def fab():
    a, b, n = 0, 1 ,0
    fablist = []
    while True:
        number = yield fablist
        while n < number:
            n += 1
            fablist.append(a)
            a, b = b ,a + b

c = fab()
#c.__next__()  #加上自定義的coroutine裝飾器之后,不需要這個初始調用了
for i in range(3,7):
    print(c.send(i*10))

continue....

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容