目錄 
         
 
          
        一、什么是包?
包是模塊的一種形式,包的本質就是一個含有.py的文件的文件夾。
二、為什么要有包?
模塊的第一個版本只有10個功能,但是未來在擴展版本的時候,模塊名和用法應該最好不要去修改,但是這只是對使用者友好,而由於版本擴展,文件越來越大,模塊設計者對模塊的管理、維護會越來越復雜,因此我們可以使用包來擴展模塊的功能。
三、如何用包?
3.1 模塊和包
導入模塊發生的三件事:
- 創建一個包的名稱空間
 - 執行py文件,將執行過程中產生的名字存放於名稱空間中。
 - 在當前執行文件中拿到一個名字aaa,aaa是指向包的名稱空間的
 
導入包發生的三件事:
- 創建一個包的名稱空間
 - 由於包是一個文件夾,無法執行包,因此執行包下的.py文件,將執行過程中產生的名字存放於包名稱空間中(即包名稱空間中存放的名字都是來自於.py)
 - 在當前執行文件中拿到一個名字aaa,aaa是指向包的名稱空間的
 
導入包就是在導入包下的.py,並且可以使用以下兩種方式導入:
- import ...
 - from ... import...
 
3.2 擴展模塊功能

如下我們如果需要擴展aaa.py模塊,需要建立一個aaa的目錄文件,並且刪除aaa.py文件,將aaa.py修改成m1.py和m2.py兩個文件,讓模塊的功能使用方法不改變。
# aaa.py
def func1():
    pass
def func2():
    pass
def func3():
    pass
def func4():
    pass
def func5():
    pass
def func6():
    pass
 
        # m1.py
def func1():
    pass
def func2():
    pass
def func3():
    pass
 
        # m2.py
def func4():
    pass
def func5():
    pass
def func6():
    pass
 
        # run.py
import aaa
aaa.func1()
aaa.func2()
aaa.func3()
aaa.func4()
aaa.func5()
aaa.func6()
 
        3.3 修改__init__.py文件
# aaa/.py
func1 = 111
func2 = 222
func3 = 333
func4 = 444
func5 = 555
func6 = 666
 
        由於在__init__.py中定義了func1,因此我們可以在run.py文件中導入func1,但是這個func1並不是我們想要的func1,因此需要修改__init__.py文件,又由於執行文件run.py的環境變量不為aaa,因此直接使用import導入m1會報錯,因此使用from導入。
# aaa/.py
from aaa.m1 import func1
from aaa.m2 import func2
 
        # run.py
import aaa
print(aaa.func1())
print(aaa.func2())
 
        3.4 導入包內包
aaa.bbb指向aaa內部的文件夾bbb包,如果我們需要導入bbb這個包。
# bbb/.py
from aaa import bbb
 
        # run.py
import aaa
print(aaa.bbb)
 
        3.5 導入包內包的模塊
如果bbb包內部有m3.py,我們需要從run.py導入m3模塊。
# bbb/.py
from aaa.bbb import m3
 
        # run.py
import aaa
aaa.bbb.m3
 
        3.6 絕對導入和相對導入
絕對導入:
# aaa/.py
from aaa.m1 import func1
from aaa.m2 import func2
 
        相對導入:
- .代表當前被導入文件所在的文件夾
 - ..代表當前被導入文件所在的文件夾的上一級
 - ...代表當前被導入文件所在的文件夾的上一級的上一級
 
from .m1 import func1
from .m2 import func2
 
         
         
        四、注意事項
- 包內所有的文件都是被導入使用的,而不是被直接運行的
 - 包內部模塊之間的導入可以使用絕對導入(以包的根目錄為基准)與相對導入(以當前被導入的模塊所在的目錄為基准),推薦使用相對導入
 - 當文件是執行文件時,無法在該文件內用相對導入的語法,只有在文件時被當作模塊導入時,該文件內才能使用相對導入的語法
 - 凡是在導入時帶點的,點的左邊都必須是一個包,
import aaa.bbb.m3.f3錯誤 

五、練習

假設我們有如上的目錄結構,文件內代碼如下:
# m1.py 
def f1():
    print('from f1')
 
        # m2.py 
def f2():
    print('from f2')
 
        # m3.py 
def f3():
    print('from f3')
 
        1.如果我們需要在run.py中實現以下邏輯代碼,因此得在__init__.py文件中如此做:
# run.py
import aaa
aaa.f1()
aaa.f2()
aaa.f3()
print(aaa.bbb)
 
        # aaa/__init__.py
from .m1 import f1
from .m2 import f2
from .bbb.m3 import f3
from . import bbb
 
        2.如果我們需要在run.py中實現以下邏輯,__init__.py什么都不需要做:
# run.py
from aaa.bbb.m3 import f3
f3()
 
       