模塊是很是簡單的Python文件,單個Python文件就是一個模塊,兩個文件就是兩個模塊。python
import語句是用來導入模塊或者從模塊裏導入特定的類或者函數。如前面咱們用過的math模塊,從而可使用sqrt函數來計算距離。程序員
假若有一個包含Database類的database.py的模塊。現有另外一個模塊爲product.py,它須要從database.py裏實例化一個Database類,而後就能夠在數據庫中執行相關產品查詢。數據庫
import database db = database.Database() #數據庫搜索操做
這時任何在database這個模塊裏面的類或者函數,均可以經過database.<something>這種激發訪問。或者,也能夠用from ... import語法來導入一個類。編程
from database import Database db = Database()
也能夠將導入的類進行重命名編程語言
from database import Database as DB # 重命名 db = DB()
也能夠在一行裏面導入多項,好比database還含有Query類函數
from database import Database, Query
可是,不少教程與經驗建議不要導入模塊裏面全部的類,以下的寫法是不採用的。測試
from database import *
一個包(package)就是放在一個文件夾裏的模塊集合。包的名字就是文件夾的名字。咱們須要作的是告訴python這個文件夾是一個包,並且把一個名爲__init__.py的文件(一般是空的)放在這個文件夾裏。若是咱們忘記建立這個文件夾,就無法從這個文件夾裏面導入那些模塊。spa
例如在咱們的工做目錄裏,把咱們的模塊放在了一個叫ecommerce(電子商務)的包裏,這個目錄一樣包含一個main.py的文件用來啓動程序。在ecommerce包裏再添加一個payments的包用來管理不一樣的付款方式,文件夾的層次結構以下所示:code
parent_directory/ main.py ecommerce/ __init__.py database.py products.py payments/ __init__.py paypal.py authorizenet.py
其中producs.py的有Product類對象
class Product: pass
database.py有Database類
class Database: pass
模塊的導入方式有兩種:絕對導入和相對導入。
要先給出這個模塊、函數的完整路徑,如在main.py須要訪問produces模塊中的Product類,使用使用以下的方法進行絕對導入:
import ecommerce.products product = ecommerce.products.Product()
或者(我的比較喜歡這種方式):
from ecommerce.products import Product product = Product()
或者:
from ecommerce import products product = products.Product()
import語句使用點號做爲分隔符來分隔包或者模塊。
上述的均可以使用,若是要導入一個模塊中的不少類,使用使用第三種方法,若是是指導入一個模塊的一兩個類,則可使用第二種方法具體指明。
在包(package)的狀況下,若是知道父模塊的名稱,那麼就可使用相對導入。好比當前在products模塊下工做,想從隔壁的database模塊導入Database類,就可使用相對導入:
from .database import Database # 點號表示使用當前路徑的database模塊
若是咱們正在編輯ecommerce.payments包裏的paypal模塊,須要引用父包裏的database模塊:
from ..database import Database # 使用兩個點號表示訪問上層的父類
若是ecommerce有contact包,該包裏有email模塊,須要將該模塊的sendEmail函數導入到paypal模塊中,
from ..contact.email import sendEmail
大部分的面向對象的編程語言都有一個「訪問控制」的概念,好比私有的(private)、受保護的(protected)和公共的(public)。但python並無這種強制規定。在技術層面上,一個類裏的全部方法和屬性都是公共可訪問的,如下有三種形式建議不一樣的訪問形式:
一、使用註釋進行提示建議。如能夠在docstring裏面放一個提示來代表這個方法只是內部使用的
二、給某個屬性或者方法加一個下劃線的前綴,大部分python程序員會把這個解釋爲「這是個內部變量,使用以前要三思」
三、給某個屬性或者方法添加一個雙下劃線的前綴,強烈建議爲內部變量。訪問時須要名稱改編(name mangling),即在該方法或者屬性前面自動加一個_<classname>的前綴(單下劃線)。
通常狀況下,不會使用加下劃線或者雙下劃線的變量。
class SecretString: ''' A not-at-all secure way to store a secret string''' def __init__(self, plain_string, pass_phrase): self.__plain_string = plain_string self.__pass_phrase = pass_phrase def decrypt(self, pass_phrase): ''' Only show the string if the pass_phrase is correct.''' if pass_phrase == self.__pass_phrase: return self.__plain_string else: return
將上述代碼存儲爲filename.py,而後使用python -i filename.py執行這個腳本,而後在交互的解釋器裏進行以下的測試:
>>> secret_string = SecretString("ACME: Top Secret", "antwerp") >>> print(secret_string.decrypt("antwerp")) ACME: Top Secret >>> print(secret_string.__plain_text) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'SecretString' object has no attribute '__plain_text' >>> print(secret_string._SecretString__plain_string) ACME: Top Secret
在ecommerce包裏有兩個模塊,一個是database.py,另外一個是products.py,假設database裏面有一個db變量,這個變量在不少地方都會被訪問,那麼咱們下面的代碼將能夠實現用import ecommerce.db取代import ecommerce.database.db。
經過在__init__.py文件(定義目錄爲包),在這裏文件中能夠包含任意變量或者類的生命,並且它會做爲這個包的一部分被咱們使用。在這個例子中,若是有ecommerce/__init__.py文件裏包含這麼一行:
from .database import db
那麼咱們就能夠用下面的語句,在mian.py或者其餘文件訪問這個db屬性了:
from ecommerce import db
以上主要在於致使ecommerce.py這個文件是一個模塊而不是包的緣由在於__init__.py。
若是你把全部代碼放在了一個單獨的模塊,以後又決定拆成一個包裏的多個包,__init__.py文件一樣對你有幫忙。
其餘模塊若是想要訪問這個新包,__init__.py文件仍然是主要的切入點。可是在內部,代碼仍然能夠被組織成許多不一樣模塊或者子包。
參考:
一、《Python3 面向對象編程》 [加]Dusty Philips 著