亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

annuaire recherche
Python是什么? Python 3 教程 Python3 基礎(chǔ)語(yǔ)法 編碼 Python3 基本數(shù)據(jù)類型 Python解釋器 Python 注釋 Python 數(shù)字運(yùn)算 Python 字符串 Python 列表 Python 編程第一步 Python 條件控制 Python 循環(huán) Python 函數(shù) Python 數(shù)據(jù)結(jié)構(gòu) Python 模塊 Python 輸入和輸出 Python 錯(cuò)誤和異常 Python 類 Python 標(biāo)準(zhǔn)庫(kù)概覽 Python Hello World 實(shí)例 Python 數(shù)字求和 Python 平方根 Python 二次方程 Python 計(jì)算三角形的面積 Python 隨機(jī)數(shù)生成 Python 攝氏溫度轉(zhuǎn)華氏溫度 Python 交換變量 Python if 語(yǔ)句 Python 判斷字符串是否為數(shù)字 Python 判斷奇數(shù)偶數(shù) Python 判斷閏年 Python 獲取最大值函數(shù) Python 質(zhì)數(shù)判斷 Python 階乘實(shí)例 Python 九九乘法表 Python 斐波那契數(shù)列 Python 阿姆斯特朗數(shù) Python 十進(jìn)制轉(zhuǎn)二進(jìn)制、八進(jìn)制、十六進(jìn)制 Python ASCII碼與字符相互轉(zhuǎn)換 Python 最大公約數(shù)算法 Python 最小公倍數(shù)算法 Python 簡(jiǎn)單計(jì)算器實(shí)現(xiàn) Python 生成日歷 Python 使用遞歸斐波那契數(shù)列 Python 文件 IO Python 字符串判斷 Python 字符串大小寫轉(zhuǎn)換 Python 計(jì)算每個(gè)月天數(shù) Python 獲取昨天日期 Python list 常用操作 Python3 實(shí)例
personnages

Python 模塊


在前面的幾個(gè)章節(jié)中我們腳本上是用python解釋器來(lái)編程,如果你從Python解釋器退出再進(jìn)入,那么你定義的所有的方法和變量就都消失了。

為此 Python 提供了一個(gè)辦法,把這些定義存放在文件中,為一些腳本或者交互式的解釋器實(shí)例使用,這個(gè)文件被稱為模塊。

模塊是一個(gè)包含所有你定義的函數(shù)和變量的文件,其后綴名是.py。模塊可以被別的程序引入,以使用該模塊中的函數(shù)等功能。這也是使用python標(biāo)準(zhǔn)庫(kù)的方法。下面是一個(gè)使用python標(biāo)準(zhǔn)庫(kù)中模塊的例子。

#!/usr/bin/python3
# Filename: using_sys.py

import sys

print('命令行參數(shù)如下:')
for i in sys.argv:
	print(i)

print('/n/nThe PYTHONPATH is', sys.path, '/n')

執(zhí)行結(jié)果如下所示:

E:\python33\src>python using_sys.py 參數(shù)1 參數(shù)2
命令行參數(shù)如下:
using_sys.py
參數(shù)1
參數(shù)2
/n/nThe PYTHONPATH is ['E:\\python33\\src', 'C:\\Windows\\system32\\python33.zip
', 'E:\\python33\\DLLs', 'E:\\python33\\lib', 'E:\\python33', 'E:\\python33\\lib
\\site-packages'] /n
  • 1、import sys引入python標(biāo)準(zhǔn)庫(kù)中的sys.py模塊;這是引入某一模塊的方法。
  • 2、sys.argv是一個(gè)包含命令行參數(shù)的列表。
  • 3、sys.path包含了一個(gè)Python解釋器自動(dòng)查找所需模塊的路徑的列表。

當(dāng)我們使用import語(yǔ)句的時(shí)候,Python解釋器是怎樣找到對(duì)應(yīng)的文件的呢?

這就涉及到Python的搜索路徑,搜索路徑是由一系列目錄名組成的,Python解釋器就依次從這些目錄中去尋找鎖引入的模塊。

這看起來(lái)很像環(huán)境變量,事實(shí)上,也可以通過(guò)定義環(huán)境變量的方式來(lái)確定搜索路徑。

搜索路徑是在Python編譯或安裝的時(shí)候確定的,安裝新的庫(kù)應(yīng)該也會(huì)修改。搜索路徑被存儲(chǔ)在sys模塊中的path變量,做一個(gè)簡(jiǎn)單的實(shí)驗(yàn),在交互式解釋器中,輸入以下代碼:

import sys
sys.path

輸出結(jié)果:

>>> sys.path
['', 'E:\\python33\\Lib\\idlelib', 'C:\\Windows\\system32\\python33.zip', 'E:\\python33\\DLLs', 'E:\\python33\\lib', 'E:\\python33', 'E:\\python33\\lib\\site-packages']

sys.path輸出是一個(gè)列表,其中第一項(xiàng)是空串'',代表當(dāng)前目錄(若是從一個(gè)腳本中打印出來(lái)的話,可以更清楚地看出是哪個(gè)目錄),亦即我們執(zhí)行python解釋器的目錄(對(duì)于腳本的話就是運(yùn)行的腳本所在的目錄)。

因此若像我一樣在當(dāng)前目錄下存在與要引入模塊同名的文件,就會(huì)把要引入的模塊屏蔽掉。

了解了搜索路徑的概念,就可以在腳本中修改sys.path來(lái)引入一些不在搜索路徑中的模塊。

現(xiàn)在,在解釋器的當(dāng)前目錄或者sys.path中的一個(gè)目錄里面來(lái)創(chuàng)建一個(gè)fibo.py的文件,代碼如下:

# Fibonacci numbers module

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

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

然后進(jìn)入Python解釋器,使用下面的命令導(dǎo)入這個(gè)模塊:

>>> import fibo

這樣做并沒(méi)有把直接定義在fibo中的函數(shù)名稱寫入到當(dāng)前符號(hào)表里,只是把模塊fibo的名字寫到了那里。

可以使用模塊名稱來(lái)訪問(wèn)函數(shù):

>>> 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]
>>> fibo.__name__
'fibo'

如果你打算經(jīng)常使用一個(gè)函數(shù),你可以把它賦給一個(gè)本地的名稱:

>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

深入模塊

模塊除了方法定義,還可以包括可執(zhí)行的代碼。這些代碼一般用來(lái)初始化這個(gè)模塊。這些代碼只有在第一次被導(dǎo)入時(shí)才會(huì)被執(zhí)行。

每個(gè)模塊有各自獨(dú)立的符號(hào)表,在模塊內(nèi)部為所有的函數(shù)當(dāng)作全局符號(hào)表來(lái)使用。

所以,模塊的作者可以放心大膽的在模塊內(nèi)部使用這些全局變量,而不用擔(dān)心把其他用戶的全局變量搞花。

從另一個(gè)方面,當(dāng)你確實(shí)知道你在做什么的話,你也可以通過(guò) modname.itemname 這樣的表示法來(lái)訪問(wèn)模塊內(nèi)的函數(shù)。

模塊是可以導(dǎo)入其他模塊的。在一個(gè)模塊(或者腳本,或者其他地方)的最前面使用 import 來(lái)導(dǎo)入一個(gè)模塊,當(dāng)然這只是一個(gè)慣例,而不是強(qiáng)制的。被導(dǎo)入的模塊的名稱將被放入當(dāng)前操作的模塊的符號(hào)表中。

還有一種導(dǎo)入的方法,可以使用 import 直接把模塊內(nèi)(函數(shù),變量的)名稱導(dǎo)入到當(dāng)前操作模塊。比如:

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

這種導(dǎo)入的方法不會(huì)把被導(dǎo)入的模塊的名稱放在當(dāng)前的字符表中(所以在這個(gè)例子里面,fibo 這個(gè)名稱是沒(méi)有定義的)。

這還有一種方法,可以一次性的把模塊中的所有(函數(shù),變量)名稱都導(dǎo)入到當(dāng)前模塊的字符表:

>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

這將把所有的名字都導(dǎo)入進(jìn)來(lái),但是那些由單一下劃線(_)開頭的名字不在此例。大多數(shù)情況, Python程序員不使用這種方法,因?yàn)橐氲钠渌鼇?lái)源的命名,很可能覆蓋了已有的定義。


__name__屬性

一個(gè)模塊被另一個(gè)程序第一次引入時(shí),其主程序?qū)⑦\(yùn)行。如果我們想在模塊被引入時(shí),模塊中的某一程序塊不執(zhí)行,我們可以用__name__屬性來(lái)使該程序塊僅在該模塊自身運(yùn)行時(shí)執(zhí)行。

#!/usr/bin/python3
# Filename: using_name.py

if __name__ == '__main__':
	print('程序自身在運(yùn)行')
else:
	print('我來(lái)自另一模塊')

運(yùn)行輸出如下:

$ python using_name.py

程序自身在運(yùn)行

$ python
>>> import using_name
我來(lái)自另一模塊
>>>

說(shuō)明: 每個(gè)模塊都有一個(gè)__name__屬性,當(dāng)其值是'__main__'時(shí),表明該模塊自身在運(yùn)行,否則是被引入。


dir() 函數(shù)

內(nèi)置的函數(shù) dir() 可以找到模塊內(nèi)定義的所有名稱。以一個(gè)字符串列表的形式返回:
</p>
<pre>
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)  
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
 '__package__', '__stderr__', '__stdin__', '__stdout__',
 '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
 '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
 'call_tracing', 'callstats', 'copyright', 'displayhook',
 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
 'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
 'thread_info', 'version', 'version_info', 'warnoptions']

如果沒(méi)有給定參數(shù),那么 dir() 函數(shù)會(huì)羅列出當(dāng)前定義的所有名稱:

>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir() # 得到一個(gè)當(dāng)前模塊中定義的屬性列表
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
>>> a = 5 # 建立一個(gè)新的變量 'a'
>>> dir()
['__builtins__', '__doc__', '__name__', 'a', 'sys']
>>>
>>> del a # 刪除變量名a
>>>
>>> dir()
['__builtins__', '__doc__', '__name__', 'sys']
>>>

標(biāo)準(zhǔn)模塊

Python 本身帶著一些標(biāo)準(zhǔn)的模塊庫(kù),在 Python 庫(kù)參考文檔中將會(huì)介紹到(就是后面的"庫(kù)參考文檔")。

有些模塊直接被構(gòu)建在解析器里,這些雖然不是一些語(yǔ)言內(nèi)置的功能,但是他卻能很高效的使用,甚至是系統(tǒng)級(jí)調(diào)用也沒(méi)問(wèn)題。

這些組件會(huì)根據(jù)不同的操作系統(tǒng)進(jìn)行不同形式的配置,比如 winreg 這個(gè)模塊就只會(huì)提供給 Windows 系統(tǒng)。

應(yīng)該注意到這有一個(gè)特別的模塊 sys ,它內(nèi)置在每一個(gè) Python 解析器中。變量 sys.ps1 和 sys.ps2 定義了主提示符和副提示符所對(duì)應(yīng)的字符串:

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>

包是一種管理 Python 模塊命名空間的形式,采用"點(diǎn)模塊名稱"。

比如一個(gè)模塊的名稱是 A.B, 那么他表示一個(gè)包 A中的子模塊 B 。

就好像使用模塊的時(shí)候,你不用擔(dān)心不同模塊之間的全局變量相互影響一樣,采用點(diǎn)模塊名稱這種形式也不用擔(dān)心不同庫(kù)之間的模塊重名的情況。

這樣不同的作者都可以提供 NumPy 模塊,或者是 Python 圖形庫(kù)。

不妨假設(shè)你想設(shè)計(jì)一套統(tǒng)一處理聲音文件和數(shù)據(jù)的模塊(或者稱之為一個(gè)"包")。

現(xiàn)存很多種不同的音頻文件格式(基本上都是通過(guò)后綴名區(qū)分的,例如: .wav,:file:.aiff,:file:.au,),所以你需要有一組不斷增加的模塊,用來(lái)在不同的格式之間轉(zhuǎn)換。

并且針對(duì)這些音頻數(shù)據(jù),還有很多不同的操作(比如混音,添加回聲,增加均衡器功能,創(chuàng)建人造立體聲效果),所你還需要一組怎么也寫不完的模塊來(lái)處理這些操作。

這里給出了一種可能的包結(jié)構(gòu)(在分層的文件系統(tǒng)中):

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

在導(dǎo)入一個(gè)包的時(shí)候,Python 會(huì)根據(jù) sys.path 中的目錄來(lái)尋找這個(gè)包中包含的子目錄。

目錄只有包含一個(gè)叫做 __init__.py 的文件才會(huì)被認(rèn)作是一個(gè)包,主要是為了避免一些濫俗的名字(比如叫做 string)不小心的影響搜索路徑中的有效模塊。

最簡(jiǎn)單的情況,放一個(gè)空的 :file:__init__.py就可以了。當(dāng)然這個(gè)文件中也可以包含一些初始化代碼或者為(將在后面介紹的) __all__變量賦值。

用戶可以每次只導(dǎo)入一個(gè)包里面的特定模塊,比如:

import sound.effects.echo

這將會(huì)導(dǎo)入子模塊:mod:song.effects.echo。 他必須使用全名去訪問(wèn):

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

還有一種導(dǎo)入子模塊的方法是:

from sound.effects import echo

這同樣會(huì)導(dǎo)入子模塊:mod:echo,并且他不需要那些冗長(zhǎng)的前綴,所以他可以這樣使用:

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

還有一種變化就是直接導(dǎo)入一個(gè)函數(shù)或者變量:

from sound.effects.echo import echofilter

同樣的,這種方法會(huì)導(dǎo)入子模塊:mod:echo,并且可以直接使用他的:func:echofilter函數(shù):

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

注意當(dāng)使用from package import item這種形式的時(shí)候,對(duì)應(yīng)的item既可以是包里面的子模塊(子包),或者包里面定義的其他名稱,比如函數(shù),類或者變量。

import語(yǔ)法會(huì)首先把item當(dāng)作一個(gè)包定義的名稱,如果沒(méi)找到,再試圖按照一個(gè)模塊去導(dǎo)入。如果還沒(méi)找到,恭喜,一個(gè):exc:ImportError 異常被拋出了。

反之,如果使用形如import item.subitem.subsubitem這種導(dǎo)入形式,除了最后一項(xiàng),都必須是包,而最后一項(xiàng)則可以是模塊或者是包,但是不可以是類,函數(shù)或者變量的名字。


從一個(gè)包中導(dǎo)入*

設(shè)想一下,如果我們使用 from sound.effects import *會(huì)發(fā)生什么?

Python 會(huì)進(jìn)入文件系統(tǒng),找到這個(gè)包里面所有的子模塊,一個(gè)一個(gè)的把它們都導(dǎo)入進(jìn)來(lái)。

但是很不幸,這個(gè)方法在 Windows平臺(tái)上工作的就不是非常好,因?yàn)閃indows是一個(gè)大小寫不區(qū)分的系統(tǒng)。

在這類平臺(tái)上,沒(méi)有人敢擔(dān)保一個(gè)叫做 ECHO.py 的文件導(dǎo)入為模塊:mod:echo還是:mod:Echo甚至:mod:ECHO。

(例如,Windows 95就很討厭的把每一個(gè)文件的首字母大寫顯示)而且 DOS 的 8+3 命名規(guī)則對(duì)長(zhǎng)模塊名稱的處理會(huì)把問(wèn)題搞得更糾結(jié)。

為了解決這個(gè)問(wèn)題,只能煩勞包作者提供一個(gè)精確的包的索引了。

導(dǎo)入語(yǔ)句遵循如下規(guī)則:如果包定義文件 __init__.py 存在一個(gè)叫做 __all__ 的列表變量,那么在使用 from package import * 的時(shí)候就把這個(gè)列表中的所有名字作為包內(nèi)容導(dǎo)入。

作為包的作者,可別忘了在更新包之后保證 __all__ 也更新了啊。你說(shuō)我就不這么做,我就不使用導(dǎo)入*這種用法,好吧,沒(méi)問(wèn)題,誰(shuí)讓你是老板呢。這里有一個(gè)例子,在:file:sounds/effects/__init__.py中包含如下代碼:

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

這表示當(dāng)你使用from sound.effects import *這種用法時(shí),你只會(huì)導(dǎo)入包里面這三個(gè)子模塊。

如果__all__真的而沒(méi)有定義,那么使用from sound.effects import *這種語(yǔ)法的時(shí)候,就*不會(huì)*導(dǎo)入包:mod:sound.effects里的任何子模塊。他只是把包:mod:sound.effects和它里面定義的所有內(nèi)容導(dǎo)入進(jìn)來(lái)(可能運(yùn)行:file:__init__.py里定義的初始化代碼)。

這會(huì)把 :file:__init__.py里面定義的所有名字導(dǎo)入進(jìn)來(lái)。并且他不會(huì)破壞掉我們?cè)谶@句話之前導(dǎo)入的所有明確指定的模塊。看下這部分代碼:

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

這個(gè)例子中,在執(zhí)行from...import前,包:mod:sound.effects中的echo和surround模塊都被導(dǎo)入到當(dāng)前的命名空間中了。(當(dāng)然如果定義了__all__就更沒(méi)問(wèn)題了)

通常我們并不主張使用*這種方法來(lái)導(dǎo)入模塊,因?yàn)檫@種方法經(jīng)常會(huì)導(dǎo)致代碼的可讀性降低。不過(guò)這樣倒的確是可以省去不少敲鍵的功夫,而且一些模塊都設(shè)計(jì)成了只能通過(guò)特定的方法導(dǎo)入。

記住,使用from Package import specific_submodule這種方法永遠(yuǎn)不會(huì)有錯(cuò)。事實(shí)上,這也是推薦的方法。除非是你要導(dǎo)入的子模塊有可能和其他包的子模塊重名。

如果在結(jié)構(gòu)中包是一個(gè)子包(比如這個(gè)例子中對(duì)于包:mod:sound來(lái)說(shuō)),而你又想導(dǎo)入兄弟包(同級(jí)別的包)你就得使用導(dǎo)入絕對(duì)的路徑來(lái)導(dǎo)入。比如,如果模塊:mod:sound.filters.vocoder 要使用包:mod:sound.effects中的模塊:mod:echo,你就要寫成 from sound.effects import echo。

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

無(wú)論是隱式的還是顯式的相對(duì)導(dǎo)入都是從當(dāng)前模塊開始的。主模塊的名字永遠(yuǎn)是"__main__",一個(gè)Python應(yīng)用程序的主模塊,應(yīng)當(dāng)總是使用絕對(duì)路徑引用。

包還提供一個(gè)額外的屬性,:attr:__path__。這是一個(gè)目錄列表,里面每一個(gè)包含的目錄都有為這個(gè)包服務(wù)的:file:__init__.py,你得在其他:file:__init__.py被執(zhí)行前定義哦。可以修改這個(gè)變量,用來(lái)影響包含在包里面的模塊和子包。

這個(gè)功能并不常用,一般用來(lái)擴(kuò)展包里面的模塊。

Article précédent: Article suivant: