1. 程式人生 > >0086-【Python系統】-python的匯入語法1

0086-【Python系統】-python的匯入語法1

匯入:

Python能對模組module和包package進行匯入。
當你在一個模組中寫的程式碼需要使用到其他模組或者包的程式碼要怎麼辦?匯入它!

Python模組

一個Python包

就是一個資料夾folder,裡面含有模組檔案(在Python 2中,這個資料夾要有一個__init__.py檔案)

工作原理

但是這個匯入到底是如何工作的呢?假如你匯入了一個模組,程式碼如下:
import abc

1. sys.modules

Python首先要做的就是在sys.modules中查詢這個abc名稱。它是先前曾被匯入過的所有模組的快取。簡單來說,就是之前被匯入過的模組,都被暫時儲存在裡面。

2. 內建的模組

如果在這個快取中找不到這個名稱,Python接下來會去內建的模組 built-in modules中查詢。這些內建模組是Python預裝的,可以在Python標準庫中檢視詳情。

3. sys.path

假如還是沒能在內建模組中找到它,Python將會去sys.path 定義的資料夾列表中搜索。通常來說,這個列表會包括當前目錄,並且會先在裡面搜尋。

當Python找到了模組,它會將這個模組繫結到區域性作用域。這就表示當前這個 abc 已經被定義了並且在被當前檔案使用而不會拋NameError的異常。

如果這個模組名沒有被找到,有就會丟擲ModuleNotFoundError這個異常。你可以在Python的官方文件找到更多內容。

語法

現在你已經瞭解匯入的工作原理了,讓我們來看一下它的語法吧。你可以匯入包和模組。(要注意一下,匯入一個包的時候,實際上就是匯入包裡面的__init__.py作為模組)你也可以從一個包或者模組中匯入指定的物件。

一般有兩種匯入的方法。當你使用第一個,你可以直接匯入該資源,如下:
1)abc可以是一個包或者模組
import abc

2)當你使用第二種語法,你從其他包或者模組中匯入資源。看下面這個例子:
from abc import xyz

xyz可以是一個模組、子包subpackage、物件object,例如類class或者函式function。

你也可以選擇重新命名匯入的資源,如下:
import abc as other_name

這會在指令碼中重新命名這個已經匯入的模組abc為other_name。現在必須使用other_name進行引用,不然就不被識別。

規範

PEP8 是Python的官方編碼規範,裡面有幾個點也是適用於匯入規範,以下是總結:

  1. 匯入應該總是寫在最前面,但需尾隨任何模組單行註釋和文件註釋。

  2. 匯入應該根據匯入的內容進行分類,一般有三種:

  • 匯入標準庫(Python的內建模組)
  • 匯入相關的第三方包(不屬於當前應用的第三方包)
  • 匯入本地應用的模組(屬於當前應用的模組)
  1. 每一組的匯入都應該用空白行分隔

請看下面這個例子:

"""展示一個標準的匯入規範

注意,匯入語句應該位於文件註釋之後

"""

# 匯入標準庫
import datetime
import os

# 匯入第三方庫
from flask import Flask
from flask_restful import Api
from flask_sqlalchemy import SQLAlchemy

# 匯入本地模組
from local_module import local_class
from local_package import local_function

以上的匯入語句被分成了三個部分,通過空白行分隔。並在每一個部分中,是根據字母排序的。

絕對匯入

絕對匯入通過使用被匯入資源在專案根目錄的完整路徑進行匯入。

語法與例項
假如你有以下目錄結構:

└── project
   ├── package1
   │   ├── module1.py
   │   └── module2.py
   └── package2
       ├── __init__.py
       ├── module3.py
       ├── module4.py
       └── subpackage1
           └── module5.py

這裡有個目錄project,它包含了兩個子目錄:package1和package2。其中package1有兩個檔案:module1.py和module2.py

package2目錄有三個檔案:兩個模組, module3.py和module4.py,也有一個初始化檔案 init.py。並且也包括一個目錄,subpackage,它包含一個檔案,module5.py

我們假設以下內容:

  1. package1/module2.py有一個函式,叫function1

  2. package2/__init.py有一個類,叫class1

  3. package2/subpackage1/module5.py有一個函式,叫function2

以下是絕對匯入的例子:

from package1 import module1
from package1.module2 import function1
from package2 import class1
from package2.subpackage1.module5 import function2

要注意你必須在頂級包目錄top-level package下提供每個包或者檔案具體的路徑。某種程度上和其檔案路徑相似,但是我們會使用點dot(.),而不用斜線slash(/)。

優缺點

應該優先考慮使用絕對路徑,因為其更簡單明瞭。使用它後,僅通過匯入語句,就知道資源是從哪裡匯入的。而且,即使當前位置的匯入語句改變了,絕對匯入還是會保持有效。並且事實上,PEP8 推薦使用絕對匯入。

當然,有時候絕對路徑會變得冗長,取決於目錄結構的複雜程度。想象一下以下這個語句:

from package1.subpackage2.subpackage3.subpackage4.module5 import function6

相對匯入在這種情況下是一個絕佳的選擇!

相對匯入

相對匯入指定了被匯入資源是相對於當前的位置 - 也就是,這個位置就是匯入語句所在的地方。有兩種型別的相對匯入:隱式和顯式。隱式相對匯入已經在Python3中被棄用了,所以這裡我就不多講了。

語法和例項

語法和例項

相對匯入的語法取決於當前的位置和被匯入模組、包以及物件的位置。以下是一些例子:

from .some_module import some_class
from ..some_package import some_function
from . import some_class

你能看到至少有一個點在每一個匯入語句的前面。相對匯入利用點符號來指定位置。

單個點表示模組或者包的引用是在同一個位置的同一個目錄下。兩個點表示它是在當前位置的父目錄中 - 意思是指上一級目錄。三個點表示它位於祖父母目錄中,以此類推。如果你使用類Unix系統的話,一定有熟悉的感覺!

假設你有和之前一樣的目錄結構:

└── project
   ├── package1
   │   ├── module1.py
   │   └── module2.py
   └── package2
       ├── __init__.py
       ├── module3.py
       ├── module4.py
       └── subpackage1
           └── module5.py

這裡有個目錄project,它包含了兩個子目錄:package1和package2。其中package1有兩個檔案:module1.py和module2.py

package2目錄有三個檔案:兩個模組, module3.py和module4.py,也有一個初始化檔案 init.py。並且也包括一個目錄,subpackage,它包含一個檔案,module5.py

重溫以下內容:

  1. package1/module2.py有一個函式,叫function1

  2. package2/__init.py有一個類,叫class1

  3. package2/subpackage1/module5.py有一個函式,叫function2

你可以通過以下方法在package1/module1.py檔案中匯入匯入function1:

# package1/module1.py

from .module2 import function1

你在這裡只需要使用一個點,因為module2.py和當前的模組module1.py是在同一個路徑下面。

你也可以在package2/module3.py中匯入class1和function2通過以下方法:

# package2/module3.py

from . import class1
from .subpackage1.module5 import function2

在第一個匯入語句中,單個點代表你從當前包中匯入class1。要謹記,匯入一個包實際上是匯入包裡的__init__.py檔案作為模組。

第二個匯入語句中,你再次使用了單個點,這是因為subpackage1和當前模組module3.py是在同一個目錄中。

優缺點

相對匯入最明顯的優點就是非常簡潔。取決於當前的位置,它可以將之前那可笑的冗長語句縮減到以下:

from ..subpackage4.module5 import function6

不幸的是,相對匯入可能會引起混亂,特別是一些目錄結構可能會改變的共享專案。且相對匯入不像絕對匯入那樣可讀,不能輕易的從匯入語句中檢視資源被匯入的位置。

結論

要記住,一般情況下,你應該選擇使用絕對匯入而不使用相對匯入,除非路徑非常的複雜,不然會使匯入語句冗長。