Python3.5入門學習記錄-模塊

模塊讓你可以有邏輯地組織你的Python代碼段。函數

把相關的代碼分配到一個 模塊裏能讓你的代碼更好用,更易懂。spa

模塊也是Python對象,具備隨機的名字屬性用來綁定或引用。設計

簡單地說,模塊就是一個保存了Python代碼的文件。模塊能定義函數,類和變量。模塊裏也能包含可執行的代碼。3d

例子code

一個叫作aname的模塊裏的Python代碼通常都能在一個叫aname.py的文件中找到。下例是個簡單的模塊common.py。orm

def printFunc(param):
    print(("Hello:{0}".format(param)))
    return

import 語句對象

想使用Python源文件,只需在另外一個源文件裏執行import語句,語法以下:blog

import module1[, module2[,... moduleN]

當解釋器遇到import語句,若是模塊在當前的搜索路徑就會被導入。索引

搜索路徑是一個解釋器會先進行搜索的全部目錄的列表。如想要導入模塊common.py,須要把命令放在腳本的頂端:ci

#導入模塊
import Common

#調用模塊裏的函數
Common.printFunc("name")

From…import語句

Python的from語句讓你從模塊中導入一個指定的部分到當前命名空間中。語法以下:

from modname import name1[, name2[, ... nameN]]

例如,要導入模塊fib的fibonacci函數,使用以下語句:

from fib import fibonacci
實例:
咱們在Common.py中在添加一個方法
def printFunc(param):
    print(("Hello:{0}".format(param)))
    return

def printFunc1(param):
    print(("Hello1:{0}".format(param)))
    return

而後引入printFunc1

from Common import printFunc1

printFunc1("printFunc1")

你們發現了麼?from…import引入的函數,不須要使用模塊名稱就能夠直接調用

From…import* 語句

把一個模塊的全部內容全都導入到當前的命名空間也是可行的,只需使用以下聲明:

from modname import *

這提供了一個簡單的方法來導入一個模塊中的全部項目

命名空間和做用域

一個Python表達式能夠訪問局部命名空間和全局命名空間裏的變量。若是一個局部變量和一個全局變量重名,則局部變量會覆蓋全局變量。

每一個函數都有本身的命名空間。類的方法的做用域規則和一般函數的同樣。

Python會智能地猜想一個變量是局部的仍是全局的,它假設任何在函數內賦值的變量都是局部的。

所以,若是要給全局變量在一個函數裏賦值,必須使用global語句。

global VarName的表達式會告訴Python, VarName是一個全局變量,這樣Python就不會在局部命名空間裏尋找這個變量了。

例如,咱們在全局命名空間裏定義一個變量money。咱們再在函數內給變量money賦值,而後Python會假定money是一個局部變量。然而,咱們並無在訪問前聲明一個局部變量money,結果就是會出現一個UnboundLocalError的錯誤。取消global語句的註釋就能解決這個問題

Money = 2000
def AddMoney():
   # 想改正代碼就取消如下注釋:
   # global Money
   Money = Money + 1
 
print Money
AddMoney()
print Money

dir()函數

dir()函數一個排好序的字符串列表,內容是一個模塊裏定義過的名字。

返回的列表容納了在一個模塊裏定義的全部模塊,變量和函數。以下一個簡單的實例:

import Common

list = dir(Common)

print(list)

輸出結果:

image

Python中的包

包是一種管理 Python 模塊命名空間的形式,採用"點模塊名稱"。

好比一個模塊的名稱是 A.B, 那麼他表示一個包 A中的子模塊 B 。

就好像使用模塊的時候,你不用擔憂不一樣模塊之間的全局變量相互影響同樣,採用點模塊名稱這種形式也不用擔憂不一樣庫之間的模塊重名的狀況。

這樣不一樣的做者均可以提供 NumPy 模塊,或者是 Python 圖形庫。

不妨假設你想設計一套統一處理聲音文件和數據的模塊(或者稱之爲一個"包")。

現存不少種不一樣的音頻文件格式(基本上都是經過後綴名區分的,例如: .wav,:file:.aiff,:file:.au,),因此你須要有一組不斷增長的模塊,用來在不一樣的格式之間轉換。

而且針對這些音頻數據,還有不少不一樣的操做(好比混音,添加回聲,增長均衡器功能,建立人造立體聲效果),所你還須要一組怎麼也寫不完的模塊來處理這些操做。

這裏給出了一種可能的包結構(在分層的文件系統中):

sound/                          頂層包
      __init__.py               初始化 sound 包
      formats/                  文件格式轉換子包
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  聲音效果子包
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  filters 子包
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

在導入一個包的時候,Python 會根據 sys.path 中的目錄來尋找這個包中包含的子目錄。

目錄只有包含一個叫作 __init__.py 的文件纔會被認做是一個包,主要是爲了不一些濫俗的名字(好比叫作 string)不當心的影響搜索路徑中的有效模塊。

最簡單的狀況,放一個空的 :file:__init__.py就能夠了。固然這個文件中也能夠包含一些初始化代碼或者爲(將在後面介紹的) __all__變量賦值。

用戶能夠每次只導入一個包裏面的特定模塊,好比:

import sound.effects.echo

這將會導入子模塊:mod:song.effects.echo。 他必須使用全名去訪問:

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

還有一種導入子模塊的方法是:

from sound.effects import echo

這一樣會導入子模塊:mod:echo,而且他不須要那些冗長的前綴,因此他能夠這樣使用:

echo.echofilter(input, output, delay=0.7, atten=4)

還有一種變化就是直接導入一個函數或者變量:

from sound.effects.echo import echofilter

一樣的,這種方法會導入子模塊:mod:echo,而且能夠直接使用他的:func:echofilter函數:

echofilter(input, output, delay=0.7, atten=4)

注意當使用from package import item這種形式的時候,對應的item既能夠是包裏面的子模塊(子包),或者包裏面定義的其餘名稱,好比函數,類或者變量。

import語法會首先把item看成一個包定義的名稱,若是沒找到,再試圖按照一個模塊去導入。若是還沒找到,恭喜,一個:exc:ImportError 異常被拋出了。

反之,若是使用形如import item.subitem.subsubitem這種導入形式,除了最後一項,都必須是包,而最後一項則能夠是模塊或者是包,可是不能夠是類,函數或者變量的名字。


從一個包中導入*

設想一下,若是咱們使用 from sound.effects import *會發生什麼?

Python 會進入文件系統,找到這個包裏面全部的子模塊,一個一個的把它們都導入進來。

可是很不幸,這個方法在 Windows平臺上工做的就不是很是好,由於Windows是一個大小寫不區分的系統。

在這類平臺上,沒有人敢擔保一個叫作 ECHO.py 的文件導入爲模塊:mod:echo仍是:mod:Echo甚至:mod:ECHO。

(例如,Windows 95就很討厭的把每個文件的首字母大寫顯示)並且 DOS 的 8+3 命名規則對長模塊名稱的處理會把問題搞得更糾結。

爲了解決這個問題,只能煩勞包做者提供一個精確的包的索引了。

導入語句遵循以下規則:若是包定義文件 __init__.py 存在一個叫作 __all__ 的列表變量,那麼在使用 from package import * 的時候就把這個列表中的全部名字做爲包內容導入。

做爲包的做者,可別忘了在更新包以後保證 __all__ 也更新了啊。你說我就不這麼作,我就不使用導入*這種用法,好吧,沒問題,誰讓你是老闆呢。這裏有一個例子,在:file:sounds/effects/__init__.py中包含以下代碼:

__all__ = ["echo", "surround", "reverse"]

這表示當你使用from sound.effects import *這種用法時,你只會導入包裏面這三個子模塊。

若是__all__真的而沒有定義,那麼使用from sound.effects import *這種語法的時候,就*不會*導入包:mod:sound.effects裏的任何子模塊。他只是把包:mod:sound.effects和它裏面定義的全部內容導入進來(可能運行:file:__init__.py裏定義的初始化代碼)。

這會把 :file:__init__.py裏面定義的全部名字導入進來。而且他不會破壞掉咱們在這句話以前導入的全部明確指定的模塊。看下這部分代碼:

import sound.effects.echo
import sound.effects.surround
from sound.effects import *

這個例子中,在執行from...import前,包:mod:sound.effects中的echo和surround模塊都被導入到當前的命名空間中了。(固然若是定義了__all__就更沒問題了)

一般咱們並不主張使用*這種方法來導入模塊,由於這種方法常常會致使代碼的可讀性下降。不過這樣倒的確是能夠省去很多敲鍵的功夫,並且一些模塊都設計成了只能經過特定的方法導入。

記住,使用from Package import specific_submodule這種方法永遠不會有錯。事實上,這也是推薦的方法。除非是你要導入的子模塊有可能和其餘包的子模塊重名。

若是在結構中包是一個子包(好比這個例子中對於包:mod:sound來講),而你又想導入兄弟包(同級別的包)你就得使用導入絕對的路徑來導入。好比,若是模塊:mod:sound.filters.vocoder 要使用包:mod:sound.effects中的模塊:mod:echo,你就要寫成 from sound.effects import echo。

from . import echo
from .. import formats
from ..filters import equalizer

不管是隱式的仍是顯式的相對導入都是從當前模塊開始的。主模塊的名字永遠是"__main__",一個Python應用程序的主模塊,應當老是使用絕對路徑引用。

包還提供一個額外的屬性,:attr:__path__。這是一個目錄列表,裏面每個包含的目錄都有爲這個包服務的:file:__init__.py,你得在其餘:file:__init__.py被執行前定義哦。能夠修改這個變量,用來影響包含在包裏面的模塊和子包。

這個功能並不經常使用,通常用來擴展包裏面的模塊。

相關文章
相關標籤/搜索