第五章 模塊與函數
5.1 python程序的結構
函數+類->模塊 模塊+模塊->包 函數+類+模塊+包=Python
python的程序由包(package)、模塊(module)和函數組成。模塊是處理某一類問題的集合,模塊由函數和類組成。包是由一系列模塊組成的集合。如圖所示:
包就是一個完成特定任務的工具箱,python提供了許多有用的工具包,如字符串處理、圖形用戶接口、Web應用、圖形圖像處理等。使用自帶的這些工具包,可以提高程序員的開發效率,減少編程的復雜度,達到代碼重用的效果。這些自帶的工具包和模塊安裝在Python的安裝目錄下的lib子目錄中。
例如,lib目錄中的xml文件夾。xml文件夾就是一個包,這個包用於完成XML的應用開發。xml包中有幾個子包:dom、sax、etree和parsers。文件__init__.py是xml包的注冊文件,如果沒有該文件,Python將不能識別xml包。在系統字典表中定義了xml包。
注意:包必須至少含有一個__init__.py文件。__init__.py文件的內容可以為空,它用於識別當前文件夾是一個包。
5.2 模塊
模塊是python中重要的概念,python的程序是由一個個模塊組成的。前面已經接觸到了模塊,一個python文件就是一個模塊。
5.2.1 模塊的創建
模塊把一組相關的函數或代碼組織到一個文件中。一個文件即是一個模塊。模塊由代碼、函數或類組成。創建一個名為myModule.py的文件,即定義了一個名為myModule的模塊。在myModule模塊中定義一個函數func()和一個類MyClass 。MyClass類中定義一個方法myFun()。
#!/usr/bin/env python #vim myModule.py #自定義模塊 def func(): #函數 print("MyModule.func()") class MyClass: #類 def myFunc(self): print("MyModule.MyClass.myFunc()")
#!/usr/bin/env python #vim call_myModule.py #調用自定義模塊的類和函數 import myModule myModule.func() myClass=myModule.MyClass() myClass.myFunc()
[root@Dannyserver danny]# python call_myModule.py
MyModule.func()
MyModule.MyClass.myFunc()
注意:模塊myModule.py和call_myModule.py需要在同一目錄下,或放在sys.path所列出的目錄下;否則python解釋器找不到自定義的模塊
當python導入一個模塊時,python首先查找當前路徑,然后查找lib目錄、site-packages目錄(Python\Lib\site-packages)和環境變量PYTHONPATH(pythonpath)設置的目錄。如果導入的模塊沒有找到,在以上路徑搜索下是否含有這個模塊。可以通過sys.path語句搜索模塊的查找路徑。
5.2.2 模塊的導入
在使用一個模塊的函數或類之前,首先要導入該模塊。模塊的導入使用import語句,如:
import module_name
這條語句可以直接導入一個模塊。調用模塊的函數或類時,需要以模塊名作為前綴,其格式如下:
module_name.func()
如果不想在程序中使用前綴符,可以使用from...import...語句導入。格式如下:
from module_name import function_name
后面調用function_name就等同於調用module_name.function_name
導入模塊下所有的類和函數,可以使用如下格式:
from module_name import *
此外,同一個模塊文件支持多條import語句。例如,定義一個名為myModule的模塊。該模塊定義一個全局變量count和一個函數func()。每次調用函數func(),使變量count的值加1。
#vim myModule.py count=1 def func(): global count count=count+1 return count
#vim a.py
import myModule print("count=", myModule.func()) myModule.count=10 print("count=",myModule.count) import myModule print("count=",myModule.func())
[root@Dannyserver test2]# python a.py count= 2 count= 10 count= 11
python中的import語句比Java的import語句更加靈活。python的import語句可以置於程序中任意的位置,甚至可以放在條件語句中,在上面的代碼段添加如下語句:
if myModule.count>1: myModule.count=1 else: import myModule print("count=", myModule.count)
輸出結果
[root@Dannyserver test2]# python a.py count= 2 count= 10 count= 11 count= 1
5.2.3 模塊的屬性
模塊有一些內置屬性,用於完成特定的任務,如__name__、__doc__。每個模塊都有一個名稱,例如,__name__用於判斷當前模塊是否是程序的入口,如果當前程序正在被使用,__name__的值為“__main__”。通常給每個模塊都添加一個條件語句,用於單獨測試該模塊的功能。例如,創建一個模塊myModule。
if __name__=="__main__": print("myModule作為主程序運行") else: print("myModule被另一個模塊調用")
單獨運行該模塊輸出結果:
[root@Dannyserver test2]# python a.py
myModule作為主程序運行
創建另一個模塊call_myModule。這么模塊很簡單,只要導入模塊myModule即可
import myModule print(__doc__) #調用了模塊另一個屬性__doc__。由於該模塊沒有定義文檔字符串,所以輸出None
[root@Dannyserver test2]# python call_myModule.py
myModule被另一個模塊調用
None
5.2.4 模塊的內置函數
Python提供了一個內聯模塊buildin。內聯模塊定義了一些開發中經常使用的函數,利用這些函數可以實現數據類型的轉換、數據的計算、序列的處理等功能。下面將介紹內聯模塊中常用的函數。
1. apply()
python3中移除了apply函數,所以不再可用了。調用可變參數列表的函數的功能只能使用在列表前添加*來實現。
2. filter()
filter()可以對某個序列做過濾處理。判斷自定義函數的參數返回的結果是否為真來過濾,並一次性返回處理結果。filter()的聲明如下所示
class filter(object)
filter(function or None,iterable) -->filter object
filter()過濾序列的功能示例:
def func(x): if (x>0): return x print (filter(func,range(-9,10))) #調用filter函數,返回的是filter對象 print(list(filter(func,range(-9,10)))) #將filter對象轉換為列表
[root@Dannyserver test2]# python a.py <filter object at 0x7fd4f762a160> #直接打印出的是filter對象,無法看到內容 [1, 2, 3, 4, 5, 6, 7, 8, 9] #將filter對象轉換為列表
說明:第三行代碼,使用range()生成待處理的列表,然后把該列表的值依次傳入func()。func返回結果給filter(),最后將結果生成一個可迭代對象返回,可以進行遍歷。
注意:filter()中的過濾函數func()的參數不能為空。否則,沒有可以存儲序列(sequence)元素的變量,func()也不能處理過濾。
3.reduce()
對序列中元素的連續操作可以通過循環來處理。例如,對某個序列中的元素累加操作。Python提供的reduce()也可以實現連續處理的功能。在python2中reduce()存在與全局空間中,可以直接調用。而在python3中將其移到了functools模塊中,所以使用之前需要先引入。reduce()的聲明如下所示:
reduce(func,sequence[ , initial]) ->value
說明:
參數func是自定義的函數,在函數func()中實現對參數sequence的連續操作。
參數sequence是待處理的序列
參數inital可以省略,如果inital不為空,則inital的值將首先傳入func()進行計算。如果sequence為空,則對initial的值進行處理。
reduce()的返回值是func()計算后的結果。
下面實現了對一個列表的數字進行累加的操作。
def sum(x,y): return (x+y) from functools import reduce #引入reduce print(reduce(sum,range(0,10))) #0+1+2+3+4+5+6+7+8+9 print(reduce(sum,range(0,10),10)) #10+0+1+2+3+4+5+6+7+8+9 print(reduce(sum,range(0,0),10)) #range(0,0)返回0,所以直接返回后面的10
[root@Dannyserver test2]# python a.py 45 55 10
注:reduce()還可以對數字進行乘法、階乘等復雜的累計計算。如果用reduce()進行累計計算,必須在sum中定義兩個參數,分別對應加法運算符兩側的操作表。
4.map()
map()可以對tuple元組進行“解包”操作,調用時設置map()的第一個參數為None。map()的功能非常強大,可以對多個序列的每個元素都執行相同的操作,並返回一個map對象。map()的聲明如下所示:
class map(object)
map(func,*iterables) -->map object
說明:
參數func()是自定義的函數,實現對序列每個元素的操作
參數iterables是待處理的序列,參數iterables的個數可以是多個
map()的返回值是對序列元素處理后的列表。
下面這段代碼實現了列表中數字的冪運算
def power(x): return (x**x) print(map(power,range(1,5))) #打印map對象 print(list(map(power,range(1,5)))) #轉換為列表輸出 def power2(x,y): return (x**y) print(map(power2,range(1,5),range(5,1,-1))) #打印map對象 print(list(map(power2,range(1,5),range(5,1,-1)))) #轉換為列表輸出,提供兩個列表參數。依次計算1^5、2^4、3^3、4^2
[root@Dannyserver test2]# python a.py <map object at 0x7f3d35d97208> [1, 4, 27, 256] <map object at 0x7f3d35d97240> [1, 16, 27, 16]
注意:如果map()中提供多個序列,則每個序列中的元素一一對應進行計算,如上。如果每個序列的長度不同,則短的序列后補充None再進行計算。