這是Python直譯器簡介的第二部分。第一部分請點選這裡 。
完成編譯之前的三個步驟都是在檢查一個簡單的函式物件。我們現在來談談更深層次的物件——函式的程式碼物件。
1 2 3 4 5 6 7 8 |
>>> def foo(a): ... x = 3 ... return x + a ... >>> foo <function foo at 0x107ef7aa0> >>> foo.func_code <code object foo at 0x107eeccb0, file "<stdin>", line 1> |
從上面的程式碼,你能發現所謂的程式碼物件就是函式物件的一個屬性。(這個函式物件還有許多其它的屬性,但它們大多都很無聊,因為 foo 函式實在是太簡單了。)
程式碼物件是在Python編譯器中生成的,並且在直譯器中完成解釋工作。它向直譯器傳遞“開工了”的資訊。我們再來看看程式碼物件的屬性。
1 2 3 4 5 6 7 |
>>> dir(foo.func_code) ['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames'] |
這個屬性列表雖然很長,但是其中大多數屬性我們今天並不會涉及。我們只關注3個有趣的 foo 函式程式碼物件的屬性。
1 2 3 4 5 6 |
>>> foo.func_code.co_varnames ('a', 'x') >>> foo.func_code.co_consts (None, 3) >>> foo.func_code.co_argcount 1 |
通過呼叫它們,我們能依次得到:變數名、函式中已知的常量和函式引數的數量。但是目前為止,我們還是不知道生成程式碼物件的指令到底是什麼。事實上,這個指令叫做位元組碼。位元組碼也是程式碼物件的一個屬性:
1 2 |
>>> foo.func_code.co_code 'd\x01\x00}\x01\x00|\x01\x00|\x00\x00\x17S' |
我們得到了許多待分解的資訊。這裡到底發生了什麼?在下一部分,我們將深入研究位元組碼。