国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

優化Python代碼使其加快作用域內的查找

2020-02-23 00:27:42
字體:
來源:轉載
供稿:網友

我將示范微優化(micro optimization)如何提升python代碼5%的執行速度。5%!同時也會觸怒任何維護你代碼的人。

但實際上,這篇文章只是解釋一下你偶爾會在標準庫或者其他人的代碼中碰到的代碼。我們先看一個標準庫的例子,collections.OrderedDict類:
 

def __setitem__(self, key, value, dict_setitem=dict.__setitem__): if key not in self:  root = self.__root  last = root[0]  last[1] = root[0] = self.__map[key] = [last, root, key] return dict_setitem(self, key, value)

注意最后一個參數:dict_setitem=dict.__setitem__。如果你仔細想就會感覺有道理。將值關聯到鍵上,你只需要給__setitem__傳遞三個參數:要設置的鍵,與鍵關聯的值,傳遞給內建dict類的__setitem__類方法。等會,好吧,也許最后一個參數沒什么意義。
作用域查詢

為了理解到底發生了什么,我們看下作用域。從一個簡單問題開始:在一個python函數中,如果遇到了一個名為open的東西,python如何找出open的值?
 

# <GLOBAL: bunch of code here> def myfunc(): # <LOCAL: bunch of code here> with open('foo.txt', 'w') as f:  pass

簡單作答:如果不知道GLOBAL和LOCAL的內容,你不可能確定open的值。概念上,python查找名稱時會檢查3個命名空間(簡單起見忽略嵌套作用域):

    局部命名空間
    全局命名空間
    內建命名空間

所以在myfunc函數中,如果嘗試查找open的值時,我們首先會檢查本地命名空間,然后是全局命名空間,接著內建命名空間。如果在這3個命名空間中都找不到open的定義,就會引發NameError異常。
作用域查找的實現

上面的查找過程只是概念上的。這個查找過程的實現給予了我們探索實現的空間。
 

def foo(): a = 1 return a def bar(): return a def baz(a=1): return a

我們看下每個函數的字節碼:
 

>>> import dis>>> dis.dis(foo) 2   0 LOAD_CONST    1 (1)    3 STORE_FAST    0 (a)  3   6 LOAD_FAST    0 (a)    9 RETURN_VALUE >>> dis.dis(bar) 2   0 LOAD_GLOBAL    0 (a)    3 RETURN_VALUE >>> dis.dis(baz) 2   0 LOAD_FAST    0 (a)    3 RETURN_VALUE

注意foo和bar的區別。我們立即就可以看到,在字節碼層面,python已經判斷了什么是局部變量、什么不是,因為foo使用LOAD_FAST,而bar使用LOAD_GLOBAL。

我們不會具體闡述python的編譯器如何知道何時生成何種字節碼(也許那是另一篇文章的范疇了),但足以理解,python在執行函數時已經知道進行何種類型的查找。

另一個容易混淆的是,LOAD_GLOBAL既可以用于全局,也可以用于內建命名空間的查找。忽略嵌套作用域的問題,你可以認為這是“非局部的”。對應的C代碼大概是[1]:

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永春县| 昂仁县| 台东县| 清水河县| 阿克陶县| 洪洞县| 凌海市| 潞西市| 临朐县| 江源县| 九江县| 涟源市| 合水县| 温泉县| 筠连县| 株洲县| 成武县| 滨海县| 叶城县| 桑植县| 泗阳县| 罗甸县| 鞍山市| 康保县| 友谊县| 望都县| 包头市| 南召县| 申扎县| 城市| 彩票| 琼海市| 光泽县| 抚松县| 临西县| 同德县| 临猗县| 房产| 夏邑县| 孟村| 游戏|