原諒我只回關於import的部份XD。這部份我發現第一次遇到很難搞懂又常常忘記,我自己
也是邊查邊寫。
import 的邏輯是什麼!?
======================
這邊比較能夠細讀的官方文件是PEP-328和
https://docs.python.org/3/tutorial/modules.html 。
## Absolute Import
Absolute import 非常簡單,只要不是以點(dot)開頭的就是absolute import,例如:
import foo
import foo.bar as bar
from foo import bar
Absolute import的邏輯就是先找built-in module,沒有的話從`sys.path`的資料夾底下
找一個<name>.py的檔案或是<name>的package(package的定義:帶有`__init__.py`)。
`sys.path`的組成包含
* 程式進入的script的資料夾
* `PYTHONPATH`環境變數
* 安裝python時指定的位置,通常是放安裝的檔案
## Relative Import
Relative import 以點作為起始,兩個點代表上一層,以此類推,而且永遠都是用
`from <> import <>` 來敘述。
至於這個"relative"是相對什麼?這個是用當前module的`__name__`來決定
* 如果它是`foo.bar`之類的值,那就是從`foo.bar`來做相對移動。
`foo`就是最上層的module。
* 如果它是`__main__`(當你執行python script的進入點),
那這個script就是最上層的module。
最後,不管是那一種relative import,都不能超過最上層的module。
## Import, the Pythonic Way
首先是,不要使用`from foo import *`這種形式。python的名字是會被覆蓋的,也就是
說如果連續兩行 `from <name> import *`然後又有重複的名字,那就會被第二行覆蓋。
然後,分開程式進入點的檔案(`__name__`是`__main__`)還有package。理由是你的進
入點會變成是`__main__`,那就沒辦法用relative import,那你就只能仰賴`sys.path`
來找你自己開發的檔案。如果你不想要自己加工`sys.path`,那就要把你的package放在
程式進入點那層,也就是這樣
project/
main.py
setup.py
packageA/
...
tests/
funtionA/
test_XXX.py
...
...
最後,盡量不要加工`sys.path`。原因跟第一點一樣是名稱衝突的問題:module是依序在
`sys.path`裡面找,加工會影響其他module,可能會讓後來的module import到錯的檔案,
這種超級難debug。
## Take Away
* absolute import: 用`sys.path`決定
* relative import: 用`__name__`決定,不能超過top-level module
* 不要用`*`、分開entrypoint和package、不要加工`sys.path`