再讀 Python Language Reference
ofollow,noindex" target="_blank">https://docs.python.org/3.6/reference/ 重讀筆記。
Lexical analysis
-
在Python原始檔中,空格將程式碼分割成token(s)。物理換行符(UNIX下的
\n
)對 Python程式沒有實際意義,Python程式認定的是NEWLINE
。 -
在Python原始檔中,一個Tab鍵在Python直譯器解釋的時候會被替換成8個空格的縮排, 而縮排對於Python有非常重要的意義。所以推薦在自己用的直譯器裡都把tab鍵替換成 4個空格(或者自己想要的空格數)。
>>> def foo(): ...print("hello")# 1 tab here ...print("world")# 4 spaces here File "<stdin>", line 3 print("world") ^ IndentationError: unindent does not match any outer indentation level
-
NEWLINE
-
顯式join:使用
\
```ipython
if True\ ... and False: ... print("False") ... ```
- 隱式join:在小括號,中括號,大括號中的行都會被合併成邏輯行(只有一個NEWLINE)
```ipython
( ... "hello" ... "world" ... ) 'helloworld' ```
-
顯式join:使用
Data model
Python中每個物件都有自己的id,型別和值。
-
Python中的物件從物件的值的可變性上分為兩類:
- mutable,例如 dict, list
- immutable,例如 str, tuple
-
從理論上來講,副作用例如開啟一個檔案,當此檔案沒有引用時是會被Python垃圾回收 的,但是由於gc無法做出保證(例如Python開啟了DEBUG模式,所有的物件都會被一個 雙鏈錶鏈著,這個時候引用計數就不為0),所以最好還是自己顯式關閉。
Execution model
-
Python程式由 code blocks 組成,block是Python執行程式碼的最小單元,block分為:
- module
- function body
- class definition
- 互動模式下每次輸入的命令都是一個block
- 每一個script file
-
$ python -c 'print("hello")'
中的命令也是一個block -
傳遞給
eval()
和exec()
的字串也是一個block,但是這兩個函式作用域規則有些特殊,會跳過LEGB中的E,也就是閉包。
每個block都在一個 execution frame 裡執行。
-
name binding
for i in ... with open(...) as ... from ... import *
只要出現了上述的binding,Python就認為這個變數名所指向的變數在當前的block裡,所以:
In [1]: foo = "hello" In [2]: def print_foo(): ...:print(foo) ...:foo = "world" ...: In [3]: print_foo() --------------------------------------------------------------------------- UnboundLocalErrorTraceback (most recent call last) <ipython-input-3-c80be14760b6> in <module>() ----> 1 print_foo() <ipython-input-2-afc4cd9aff75> in print_foo() 1 def print_foo(): ----> 2print(foo) 3foo = "world" 4 UnboundLocalError: local variable 'foo' referenced before assignment In [4]:
- "The global statement has the same scope as a name binding operation in the same block. If the nearest enclosing scope for a free variable contains a global statement, the free variable is treated as a global."
沒看懂,來自:https://docs.python.org/3.6/reference/executionmodel.html
- 類定義的變數作用域侷限於類內,而不會擴充套件至方法和表示式,generator裡,所以:
In [1]: class Foo: ...:hello = "hello" ...:def foo(self): ...:print(hello) ...: In [2]: Foo().foo() --------------------------------------------------------------------------- NameErrorTraceback (most recent call last) <ipython-input-2-6c4f5adc4d1e> in <module>() ----> 1 Foo().foo() <ipython-input-1-029db0d572c9> in foo(self) 2hello = "hello" 3def foo(self): ----> 4print(hello) 5 NameError: name 'hello' is not defined In [3]: class Foo: ...:a = 32 ...:b = [a + i for i in range(10)] ...: --------------------------------------------------------------------------- NameErrorTraceback (most recent call last) <ipython-input-3-395876c62295> in <module>() ----> 1 class Foo: 2a = 32 3b = [a + i for i in range(10)] 4 <ipython-input-3-395876c62295> in Foo() 1 class Foo: 2a = 32 ----> 3b = [a + i for i in range(10)] 4 <ipython-input-3-395876c62295> in <listcomp>(.0) 1 class Foo: 2a = 32 ----> 3b = [a + i for i in range(10)] 4 NameError: name 'a' is not defined In [4]:
- 閉包內的變數(free variables)的值是在執行時確定的:
In [1]: foo = "hello" In [2]: def f(): ...:print(foo) ...: In [3]: f() hello In [4]: foo = "world" In [5]: f() world In [6]:
The import system
-
import
語句包含兩個部分__import__ __import__
-
匯入的時候,會根據點號依次匯入,而且會首先搜尋
sys.modules
,例如:
In [1]: import sys In [2]: sys.modules['tornado'] --------------------------------------------------------------------------- KeyErrorTraceback (most recent call last) <ipython-input-2-36f3d84239fe> in <module>() ----> 1 sys.modules['tornado'] KeyError: 'tornado' In [3]: sys.modules['tornado.web'] --------------------------------------------------------------------------- KeyErrorTraceback (most recent call last) <ipython-input-3-f1a34b2734fb> in <module>() ----> 1 sys.modules['tornado.web'] KeyError: 'tornado.web' In [4]: import tornado.web In [5]: tornado Out[5]: <module 'tornado' from '/usr/local/lib/python3.5/dist-packages/tornado/__init__.py'> In [6]: tornado.web Out[6]: <module 'tornado.web' from '/usr/local/lib/python3.5/dist-packages/tornado/web.py'> In [7]: sys.modules['tornado'] Out[7]: <module 'tornado' from '/usr/local/lib/python3.5/dist-packages/tornado/__init__.py'> In [8]: sys.modules['tornado.web'] Out[8]: <module 'tornado.web' from '/usr/local/lib/python3.5/dist-packages/tornado/web.py'> In [9]: