python學習筆記系列----(四)模塊


    這一章主要是敘述了python模塊的概念以及包的概念,還有它們的使用;收獲也是大大的。

    提起python文件,經常會聽到3個名詞,python腳本,python模塊,python包。腳本的概念是從python交互式命令行引用過來的,把在命令行內運行的代碼段復制到一個文件里再運行,這個文件就可以稱為一個腳本;腳本之間可能存在相同的函數等,為了一個腳本能使用另一個腳本里的函數等,這里的另一個腳本就可以稱為一個模塊,也就是說一個模塊里的定義是可以被導入到別的模塊或者主模塊中使用的;python包是python管理模塊命名空間的一種方式,類似python模塊解決了不同模塊之間的全局變量的重名,python包解決了多個模塊組成的包時模塊名的重名。

4.1 模塊

     模塊是包含 Python 定義和聲明的文件。文件名就是模塊名加上.py 后綴。可以通過可以全局變量 __name__ 的值得到。每個模塊都有自己的私有符號表(程序源代碼中的每個標識符都和它的聲明或使用信息綁定在一起,比如其數據類型、作用域以及內存地址。)。模塊里的所有定義把這個表當成全局符號表。所以這個模塊的使用者可以在這個模塊內使用全局變量而不需要擔心與用戶的全局變量沖突。

4.1.1 模塊的導入

    模塊的導入語句一般常規性的會放在一個模塊的最開始部分;被導入的模塊名就會被放置到使用該模塊的模塊的全局符號表內。

    模塊的導入有2種方法:

   A:import modname.submodname。其中這種方式只能導入包,而且只有父包的包名會被放置到引入該模塊的模塊的全局符號內,也就是說通過這個方式導入了包,如果要使用包內的函數或者一些變量,需要進入父包,再進入父包內的符號表內,得到那些定義。

下面有2個例子:第一個例子,python的安裝子目錄下有一個pip包,下面有子包以及子模塊等,接下來會以這個包為例進行說明:

>>> print dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> import pip
>>> print dir()
['__builtins__', '__doc__', '__name__', '__package__', 'pip']
>>> import pip.index
>>> print dir()
['__builtins__', '__doc__', '__name__', '__package__', 'pip']
>>> import pip.index.egg_info_matches
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named egg_info_matches

在使用import語句導入該模塊后,當前的全局符號表內多了包名pip;待再次導入子模塊,全局符號表並沒有增加子模塊的名字;用import語句企圖導入子文件內的函數時,提示不存在這個模塊。

例2是通過這類導入,如何使用包內各種定義的問題。因為導入后當前的全局符號表內,只有包名,所以要使用子模塊的方法,必須通過.的方式,從包到子模塊,再到具體的方法或者其他定義。

# Fibonacci numbers module

def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print b,
        a, b = b, a+b

def fib2(n):   # return Fibonacci series up to n
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a+b
    return result
>>> import fibo
>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

 B. from modname.submodname import subsubmodname or  function

    通過這個方法,可以直接導入一個包下的子模塊,或者直接導入子模塊下的函數。在例子中,企圖在import語句后導入子文件的函數名,會提示存在語法錯誤。但是導入子文件或者函數是沒問題的。

>>> print dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> from pip import index
>>> print dir()
['__builtins__', '__doc__', '__name__', '__package__', 'index']
>>> from pip import index.egg_info_matches
  File "<stdin>", line 1
    from pip import index.egg_info_matches
                         ^
SyntaxError: invalid syntax
>>> from pip.index import egg_info_matches
>>> print dir()
['__builtins__', '__doc__', '__name__', '__package__', 'egg_info_matches', 'inde
x']

如果使用from pip import index語句,要調用index內函數時,使用index.egg_info_matches進行調用。

如果使用from pip.index import egg_info_matches語句,要調用index內egg_info_matches函數時,直接使用egg_info_matches即可,但是如果企圖調用該模塊內的其他函數,會報錯。

4.1.2  dir()函數

   dir()是內置函數里的一個,是用來列出模塊中定義了哪些名字,然后返回一個list字符串。里面包含變量名,模塊名,函數名等等。使用help查看dir的使用,可以得到更多的小細節。

4.1.3 模塊的搜索路徑 

     導入一個模塊時,python是怎么搜索這個模塊的呢?首先,解析器會從內置模塊內查找是否存在,如果不存在,就會從sys.path這個路徑下進行搜索,這個路徑包含以下三個部分:

    A. 包含當前文件的文件夾

    B. python配置的path下

    C. python的默認安裝目錄下

   腳本所在的目錄被放置在搜索路徑的最開始,也就是在標准庫的路徑之前。這意味着將會加載當前目錄中的腳本,如果庫目錄中具有相同名稱的模塊則不會被加載。除非是有意想替換標准庫,否則這應該被當成是一個錯誤。

   python的sys.path是可以被修改的,但是其他文件運行時不會使用到該列表(或者執行完后再打印sys.path之前添加的目錄就消失了)。

>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')

4.1.4 標准模塊

   python 官網內有一個文檔“Library Reference”是介紹標准模塊的,標准模塊里有一部分的模塊是直接構建在解釋器內,使用import后就能直接使用,常見的有以下幾個:

 4.2 包

     包的基本概念在介紹模塊的時候已經提及了,為了讓python能識別一個目錄是python包,需要在目錄里增加__init__.py文件,這個文件可以是空的,可以對包進行初始化或者設置__all__ 參數。

     設置_all__參數的主要原因是:為包提供顯式的索引。import 語句使用以下約定: 如果包中的 __init__.py 代碼定義了一個名為__all__的列表,那么在遇 到 from package import *語句的時候,應該把這個列表中的所有模塊名字導入。當包有新版本包發布時,就需要包的作者更新這個列表了。如果包的作者認為不可以用 import * 方式導入它們的包,也可以決定不支持它。如果 __all__ 沒有定義,From a Package Importing * 語句 不會從包中導入所有的子模塊到當前命名空間;它只保證包已經被導入。(在pip的該文件內未找到_all__參數的賦值,但是導入的時候卻能全部導入;自己測試的時候,不給_all__參數賦值,確實又只能導入包。暫時還未解,可能做了另一種等效的賦值)

     導入模塊或者方法時,還有一種方法:From a Package Importing * ,對PIP包進行嘗試結果如下:

>>> print dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> from pip import *
>>> print dir()
['CommandError', 'ConfigOptionParser', 'FrozenRequirement', 'InsecureRequestWarning', 'InstallationError', 'PipError', 'UpdatingDefaultsHelpFormatter', '__builtins__', '__doc__', '__name__', '__package__', 'absolute_import', 'autocomplete', 'basecommand', 'baseparser', 'bazaar', 'check_isolated', 'cmdoptions', 'commands', 'commands_dict', 'compat', 'create_main_parser', 'deprecation', 'dist_is_editable', 'download', 'exceptions', 'get_installed_distributions', 'get_prog', 'get_similar_commands', 'get_summaries', 'git', 'index', 'locale', 'locations', 'logger', 'logging', 'main', 'mercurial', 'models', 'operations', 'optparse', 'os', 'parseopts', 'pep425tags', 'pip', 're', 'req', 'status_codes', 'subversion', 'sys', 'utils', 'vcs', 'warnings', 'wheel']

      結果PIP下所有的子包和子模塊全部都導進來了。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM