函式 宣告
def name([arg,... arg = value,... *arg, **kwarg]):
suite
包括函式在內的所有物件都是第⼀類物件,可作為其他函式的實參或返回值。
• 在名字空間中,名字是唯⼀主鍵。因此函式在同⼀範圍內不能 "過載 (overload)"。
• 函式總是有返回值。就算沒有 return,預設也會返回 none。
• 支援遞迴調⽤,但不進⾏尾遞迴優化。最⼤深度 sys.getrecursionlimit()。
不同於⽤ def 定義複雜函式,lambda 只能是有返回值的簡單的表示式。使⽤用賦值語句會引發語法錯誤,可以考慮用函式代替。引數
>>> def test(a, b):
... print a, b
>>> test(1, "a")! ! ! # 位置引數
1 a>>> test(b = "x", a = 100)!! # 命名引數
100 x
函式的傳參方式靈活多變,可按位置順序傳參,也可不關心順序用命名實參。
⽀持引數預設值。不過要⼩心,預設值物件在建立函式時⽣生成,所有調⽤都使⽤同一物件。如果該預設值是可變型別,那麼就如同 c 靜態區域性變數。
用 *args 收集 "多餘" 的位置引數,**kwargs 收集 "額外" 的命名引數。這兩個名字只是慣例,可自由命名。
變參只能放在所有引數定義的尾部,且 **kwargs 必須是最後⼀個。
可 "展開" 序列型別和字典,將全部元素當做多個實參使用。如不展開的話,那僅是單個實參物件。
單個 "*" 展開序列型別,或者僅是字典的主鍵列表。"**" 展開字典鍵值對。但如果沒有變參收集,展開後多餘的引數將引發異常。
lambda 同樣支援預設值和變參,使用方法完全一致。
作用域
函式形參和內部變數都儲存在locals名字空間中。
除⾮使用 global、nonlocal 特別宣告,否則在函式內部使⽤賦值語句,總是在 locals 名字空間中新建⼀個物件關聯。注意:"賦值" 是指名字指向新的物件,⽽非通過名字改變物件狀態。不改變外部global的物件,只是在函式內建立了乙個新的物件。
如果僅僅是引用外部變數,那麼按legb順序在不同作用域查詢該名字。
名字查詢順序: locals -> enclosing function -> globals -> __builtins__
• locals: 函式內部名字空間,包括區域性變數和形參。
• enclosing function: 外部巢狀函式的名字空間。
• globals: 函式定義所在模組的名字空間。
• __builtins__: 內建模組的名字空間。
通常內建模組 __builtin__ 在本地名字空間的名字是 __builtins__ (多了個 s 結尾)。但要記住這說法⼀點也不靠譜,某些時候它⼜會莫名其妙地指向 __builtin__.__dict__。如實在要操作該模組,建議顯式 import __builtin__。
現在,獲取外部空間的名字沒問題了,但如果想將外部名字關聯到⼀個新物件,就需要使⽤用 global關鍵字,指明要修改的是 globals 名字空間。python 3 還提供了 nonlocal 關鍵字,⽤用來修改外部巢狀函式名字空間,可惜 2.7 沒有
這種實現通過 _getframe() 來獲取外部函式堆疊幀名字空間,存在一些限制。因為拿到是調⽤者,而不⼀定是函式建立者。需要注意,名字作⽤用域是在編譯時確定的。
要解決這個問題,可動態訪問名字,或使⽤ exec 語句,直譯器會做動態化處理。如果函式中包含 exec 語句,編譯器生成的名字指令會依照 legb 規則搜尋
直譯器會將 locals 名字複製到 fast 區域來優化訪問速度,因此直接修改 locals 名字空間並不會影響該區域。解決⽅法還是用 exec。
另外,編譯期作⽤域不受執行期條件影響。其中細節,可以用dis反編譯檢視生成的位元組指令。
堆疊幀python堆疊幀基本上就是對x86的模擬,用指標對應bp,sp,ip暫存器。堆疊幀塵緣包括函式執行所需的名字空間、呼叫堆疊鍊錶、異常狀態等。
可使⽤ sys._getframe(0) 或 inspect.currentframe() 獲取當前堆疊幀。其中 _getframe() 深度引數為 0 表⽰示當前函式,1 表⽰調⽤堆疊的上個函式。
許可權管理:通過呼叫堆疊檢查函式caller,以實現許可權管理。
上下文:通過呼叫堆疊,我們可以隱式向整個執行流程傳遞上下文物件。inspect.stack 比 frame.f_back更方便點。sys._current_frames 返回所有執行緒的當前堆疊幀物件。虛擬機會快取 200 個堆疊幀復⽤物件,以獲得更好的執⾏效能。
>>> import inspect
>>> def get_context():
... for f in inspect.stack():! ! ! # 迴圈調⽤用堆疊列表。
... context = f[0].f_locals.get("context")! # 檢視該堆疊幀名字空間中是否有⺫⽬目標。
... if context: return context! ! ! # 找到了就返回,並終⽌止查詢迴圈。
>>> def controller():
... context = "contextobject"! ! ! # 將 context 新增到 locals 名字空間。
... model()
>>> def model():
... print get_context()! ! ! ! # 通過調⽤用堆疊查詢 context。
>>> controller()! ! ! ! ! ! # 測試通過。
contextobject
Python學習 學習筆記(一)
python是什麼?人們為和使用python python的缺點 如今誰在使用python 流行的p2p檔案分享系統bitjorrent是乙個python程式。eve online這款大型多人網路遊戲 massively multiplayer online game,mmog 廣泛地使用pytho...
python學習學習筆記一
1,python 是完全物件導向的語言。在python中一切都是物件,函式 模組 字串等都是物件。2,資料型別 數字,字串,列表,元組,字典 數字型 整型 浮點型 布林型 非零即真 複數型 int x float x 型別轉換 非數字型 字串 列表 元祖 字典 list 元祖 元祖轉列表 tuple...
Python學習筆記 一
python學習筆記 一 關鍵知識點 1 程式列印輸出使用print語句 2 使用print輸出字串時,字串內容不帶引號。而使用字串變數名輸出時,字串內容由引號括起來 3 在python 解析器中下劃線 表示最後乙個表示式的值 4 重定向輸出符合為 5 程式中需要輸入時,實用raw input 內建...