包介紹

給你骨質唱疏鬆發表於2020-12-19

一.什麼是包

  • 包就是一個含有__init__.py檔案的資料夾

  • 包其實就是一個"超級模組", 用來被匯入使用

ps : __init__.py 檔案的作用

?當你執行一個資料夾的時候,需要一個檔案可以替代資料夾的執行,"__init__.py"的作用就在於此
?在"python3", 即使包下沒有"__init__.py"檔案, "import"匯入也不會報錯, 而在"Python2", 包下面一定要有該檔案
?建立包的目的不在於執行, 而是用來被匯入使用的, 他就是模組的一種形式, 本質就是模組

二.為什麼用包

  • 當你的功能越來越多, 我們無法把所有的功能都寫進同一個檔案中去
  • 於是我們使用模組組織功能, 當模組越來越多呢
  • 我們就需要用資料夾將模組檔案組織起來, 以此來提高程式的結構性和可維護性
  • 包就是一個資料夾

三.使用包的注意事項

  • 包的匯入與模組的匯入一樣使用 from...importimport
  • 匯入時帶點 : . 的, 點的左邊必須是一個包, 否則非法, 可以帶有一連串的點, 這是匯入包特有的語法
  • 使用 from...import 匯入時, import後面必須是一個明確的名字, 不能有任何的字首

四.匯入包發生的三件事

  • 產生一個包的名稱空間
  • 執行包下的 __init__.py 檔案, 將產生的名字存放於包的名稱空間中
  • 在當前執行檔案中拿到一個名字包資料夾名, 該名字指向包的名稱空間
?假設我建立一個名為 "aaa" 的包
import aaa   # 匯入包 "aaa"

print(aaa.x)  # "aaa.x"就是向 "__init__.py" 要一個名字 "x"

五.絕對匯入

  • 包裡面的匯入都是包內模組之間的相互匯入, 不是用來執行的
  • 絕對匯入都是以包的頂級路徑作為起始點
  • 絕對匯入沒有任何限制, 是通用的一種匯入方式

1.一層包示例

image-20201211154019044

  • 頂級包 : aaa
  • 子模組 : xxx.py yyy.py
?"__init__.py" 內容
print("i am aaa.__init__")  # 包被匯入就會被執行

from aaa.xxx import f1
from aaa.yyy import f2

?"xxx.py" 內容
def f1():
    print("i am xxx")
    
?"yyy.py" 內容
def f2():
    print("i am yyy") 
   
?"run.py" 內容  # 執行檔案
import aaa

aaa.f1()
aaa.f2()
''' 執行結果
i am aaa.__init__
i am xxx
i am yyy
'''

2.二層包示例

image-20201211155416322

  • 頂級包 : aaa
  • 頂級包.子模組 : xxx.py yyy.py
  • 子包 : bbb
  • 子包子.模組 : zzz.py
?"aaa""__init__.py" 內容
from aaa.xxx import f1
from aaa.yyy import f2
from aaa.bbb.zzz import f3

?"xxx.py" 內容
def f1():
    print("i am f1")
    
?"yyy.py" 內容
def f2():
    print("i am f2")

?"bbb""__init.py" 內容
from aaa.bbb.zzz import f3

?"zzz.py" 內容
def f3():
    print("i am f3")
    
?"run.py"  內容  # 執行檔案
import aaa

aaa.f1()   # 沒有改變使用者的呼叫方式
aaa.f2()   
aaa.f3()
''' 執行結果
i am f1
i am f2
i am f3
'''

六.相對匯入

  • 相對匯入只能使用 from...import..., 使用 import .f1報錯
  • . 代表當前檔案所在的目錄, .. 代表當前檔案的上一級目錄, ... 以此類推
  • 相對匯入不能跨出包, (就是不能...點出了頂級包), 僅限於包內模組的相對匯入
  • 針對包內部模組之間的相互匯入, 推薦使用相對匯入

1.示例

image-20201211161557717

  • 頂級包 : mmm
  • 子模組 : m1.py m2.py m3.py
?"__init__.py"  內容
from .m1 import f1
from .m2 import f2
from .m3 import f3

?"m1.py"  內容
def f1():
    print("i am m1.f1")
    
?"m2.py"  內容
def f2():
    print("i am m2.f2")
    
?"m3.py"  內容
def f3():
    print("i am m3.f3")
    
?"run.py"  內容
import mmm

mmm.f1()   # 使用者呼叫方式不變
mmm.f2()
mmm.f3()
'''  執行結果
i am m1.f1
i am m2.f2
i am m3.f3
'''

七.絕對匯入與相對匯入總結

1.絕對匯入

  • 以執行檔案的 sys.path 為起始點開始匯入
  • 優點 : 執行檔案與被執行的檔案中都可以使用
  • 缺點 : 所有的匯入都是以 sys.path 為起始點, 匯入麻煩

2.相對匯入

  • 參照當前所在檔案的資料夾為起始點開始查詢
  • 優點 : 匯入更加簡單
  • 缺點 : 只能在包內模組相互匯入時才能使用

八.from…import *

  • * 代表匯入所有
  • 可以使用 __all__=["xxx","yyy"] 來控制能使用的模組
  • __all__ 是在 __init__.py 檔案下定義的

ps : 使用者無法區分模組是檔案還是一個包,我們定義包是為了方便開發者維護

相關文章