1.Python程序的結構
Python的程序由包(package)、模塊(module)和函數組成。
模塊是處理一類問題的集合,由函數和類組成。
包是由一系列模塊組成的集合。包是一個完成特定任務的工具箱。
2.函數
2.1函數的定義
def sayHello(): print 'Hello World!' # block belonging to the function sayHello()
2.2函數的參數
Python中任何東西都是對象,所以參數只支持引用傳遞的方式。Python通過名稱綁定的機制,把實際參數的值和形式參數的名稱綁在一起。即形參與實參指向內存中同一個儲存空間。
def arithmetic (x = 1, y = 1, operator = "+"): result = { "+" : x + y, "-" : x - y, "*" : x * y, "/" : x / y } return result.get(operator) print (arithmetic(1,2)) print (arithmetic(y = 2, operator = "-") print (arithmetic(y = 3, x = 1, operator = "*") # 使用賦值表達式傳遞參數,可以顛倒參數列表的順序
# 列表作為參數 def arithmetic (args = [], operator = "+"): x = args[0] y = args[1] result = { "+" : x + y, "-" : x - y, "*" : x * y, "/" : x / y } return result.get(operator) print (arithmetic([1,2]))
# 使用默認參數出現預期外結果 def append(args = []): args.append(0) print (args) append() # [0] append([1]) # [1,0] append() # [0,0] , 使用的仍是第一次調用的args # 避免重復問題 def append(args = []): if len(args) <= 0 # 若args中沒有元素,將其列表置空 args = [] args.append(0) print(args) append() # [0] append([1]) # [1,0] append() # [0]
# 傳遞可變參數 def func(*args): # 傳入的實參被“打包”到一個args元組中 print args func(1,2,3)
1 # 傳遞可變參數——字典 2 def search (*t, **d): # 在形參前加"**",可以引用一個字典 3 keys = d.keys() 4 values = d.values() 5 print (keys) 6 print (values) 7 for args in t: 8 for key in keys: 9 if args == key: 10 print ("find:", d[key]) 11 12 search("one", "three", one = "1", two = "2", three = "3")
2.3函數的返回值
返回值用return語句,其后可為變量或表達式。Python中即使函數無返回值,依舊可以獲得返回值None。或者return不帶任何參數時,也返回None。
# return返回多個值,打包到元組內 def func(x,y,z): l = [x,y,z] l.reverse() numbers = tuple(l) # a,b,c = tuple(l) return numbers # return a,b,c x,y,z = func(0,1,2) print (x,y,z)
2.4函數的嵌套
Python不僅支持函數體內嵌套,還支持函數定義的嵌套。
# 在函數體內部定義函數 def func(): x=1 y=2 m=3 n=4 def sun(a,b): return a+b def sub(a,b):; return a-b return sum(x,y) * sub(m,n) print(func())
# 嵌套函數,直接使用外層函數的變量 def func(): x=1 y=2 m=3 n=4 def sun(): return x+y def sub():; return m-n return sum() * sub() print(func())
PS:盡量不要在函數內部定義函數,不便於程序維護
2.5遞歸函數
# 計算階乘 def refunc(n): i=1 if n > 1: i = n n = n * refunc(n-1) print ("%d! =" %i,n) return n refunc(5) # output: 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120
# 使用reduce計算階乘 From functools import reduce print ("5! =", reduce(lambda x, y: x * y, range(1,6)))
2.6lambda函數
用於創建一個匿名函數,函數名未和標識符進行綁定。使用lambda函數可以返回一些簡單的運算結果。通常把lambda賦值給一個變量,該變量就可以作為函數使用。
func = lambda 變量1,變量2,... : 表達式 func()
# lambda def func(): x=1 y=2 m=3 n=4 sum = lambda x, y : x + y print (sum) sub() = lambda m, n : m - n print (sub) return sum(x,y) * sub(m,n) print(func())
# lambda的函數用法 print ( (lambda x : -x) (-2)) #給x賦值-2
PS:lambda中只能使用表達式,不能使用判斷、循環等多重語句。
2.7Generator函數
生成器(Generator)的作用是一次產生一個數據項,並把數據項輸出。Generator函數可以用在for循環中遍歷。Generator函數每次返回一個數據項的特性,使得迭代器的性能更佳。
# 定義Generator函數 def func(n): for i in range(n): yield i # 在for循環中輸出 for i in func(3): print (i) # 0 1 2 # 使用next()輸出 r = func(3) print (r.next()) # 0 print (r.next()) # 1 print (r.next()) # 2 print (r.next()) # 已無數據生成,拋出異常StopIteration
# yield 與 return的區別 def func(n): for i in range(n): return i # return 函數運行到此為止 def func2(n): for i in range(n): yield i # 循環生成n個數,不會被終止 print (func(3)) # 0 f = func2(3) print (f) # 返回函數func2的地址 print (f.next()) # 0 print (f.next()) # 1
Generator函數依次只趕回一個數據項,占用更少的內存。每次生成數據都要記錄當前的狀態,便於生成下一次數據。數據的訪問通過next()實現。當 訪問越界時,拋出異常StopIteration。
2.8global語句
如果你想要為一個定義在函數外的變量賦值,那么你就得告訴Python這個變量名不是局部的,而是 全局 的。我們使用global語句完成這一功能。沒有global語句,是不可能為定義在函數外的變量賦值的。
def func(): global x print 'x is', x # 50 x = 2 print 'Changed local x to', x # 2 x = 50 func() print 'Value of x is', x # 2
3.模塊
3.1使用sys模塊
import sys # from sys import argv print 'The command line arguments are:' for i in sys.argv: print i print '\n\nThe PYTHONPATH is', sys.path, '\n' # output The command line arguments are: using_sys.py we are arguments The PYTHONPATH is ['/home/swaroop/byte/code', '/usr/lib/python23.zip', '/usr/lib/python2.3', '/usr/lib/python2.3/plat-linux2', '/usr/lib/python2.3/lib-tk', '/usr/lib/python2.3/libdynload', '/usr/lib/python2.3/site- packages', '/usr/lib/python2.3/site-packages/gtk-2.0']
Python中的import語句可以置於程序的任何位置。
sys模塊包含了與Python解釋器和它的環境有關的函數。
sys.argv變量是一個字符串的列表 。特別地,sys.argv包含了命令行參數的列表,即使用命令行傳遞給你的程序的參數。
這里,當我們執行python using_sys.py we are arguments的時候,我們使用python命令 運行using_sys.py模塊,后面跟着的內容被作為參數傳遞給程序。Python為我們把它存儲 在sys.argv變量中。
腳本的名稱總是sys.argv列表的第一個參數。所以,在這里,'using_sys.py'是sys.argv[0]、'we'是sys.argv[1]、'are'是sys.argv[2]以 及'arguments'是sys.argv[3]。
sys.path包含輸入模塊的目錄名列表。我們可以觀察到sys.path的第一個字符串是空的——這個空的字符串表示當前目錄也是sys.path的一部分,這與PYTHONPATH環境變量是相同的。這意味着你可以直接輸入位於當前目錄的模塊。否則,你得把你的模塊放在sys.path所列的目錄之一。
3.2.pyc文件
使輸入模塊更加快的方法:
創建字節編譯的文件 ,這些文件以.pyc作為擴展名。字節編譯的文件與Python變換程序的中間狀態有關。當你在下次從別的程序輸入這個模塊的時候,.pyc文件是十分有用的——它會快得多,因為一部分輸入模塊所需的處理已經完成了。另外,這些 字節編譯的文件也是與平台無關的。
3.3模塊的__name__
當一個模塊被第一次輸入的時候,這個模塊的主塊將被運行。假如我們只想在程序本身被使用的時候運行主塊,而在它被別的模塊輸入的時候不運行主塊,這可以通過模塊的 __name__屬性完成。
_name_用於判斷當前模塊是否是程序的入口,如果當前程序正在被使用,_name_的值為"_main_"。
if __name__ == '__main__': print 'This program is being run by itself' else: print 'I am being imported from another module'
# output This program is being run by itself $ python >>> import using_name I am being imported from another module
每個Python模塊都有它的__name__,如果它是'__main__',這說明這個模塊被用戶單獨運行,我們 可以進行相應的恰當操作。
3.4模塊的創建
模塊把一組相關的函數或代碼組織到一個文件中。一個文件即是一個模塊。模塊由代碼、函數或類組成。創建一個名為myModule.py的文件,即定義了一個名為myModule的模塊。
# 自定義模塊 def func(): print ("MyModule.func()" ) class MyClass: def myFunc(self): print ("MyModule.MyClass.myFunc()") # 在myModule.py所在目錄下創建一個call_myModule.py的文件。在該文件中調用myModule模塊的函數和類 import myModule myModule.func() myClass = myModule.MyClass() myClass.myFunc()
另一個例子:
# Filename: mymodule.py def sayhi(): print 'Hi, this is mymodule speaking.' version = '0.1' # 調用mymodule模板 import mymodule # from mymodule import sayhi, version mymodule.sayhi() print 'Version', mymodule.version # output $ python mymodule_demo.py Hi, this is mymodule speaking. Version 0.1
3.5模塊的內置函數
Python提供了一個內聯模板buildin。內聯模板定義了一些開發中經常使用的函數,利用這些函數可以實現數據類型的轉換、數據的計算、序列的處理等功能。
- filter()
對某個序列做過濾處理,判斷自定義函數的參數返回的結果是否為真來過濾,並一次性返回處理結果。
# 聲明 class filter(object) filter(function or None, iterable) --> filter object
# 功能 def func(x): if x > 0: return x # 使用range()生成待處理的列表,然后把該列表的值依次傳入func(),func()返回結果給filter(),最后將結果yield成一個iterable對象返回,依次遍歷 # output <filter object at 0x1022b2750> # 直接打印出filter對象。最后一行將其轉換為列表 print ( filter (func,range(-9,10)) ) # 調用filter函數,返回filter對象 print ( list(filter(func,range(-9,10))) # 將filter對象轉換為列表
filter()中的過濾函數func()的參數不能為空。否則,沒有可以存儲sequence元素的變量,func()也不能處理過濾
- reduce()
實現連續處理的功能,存在於functools模塊中。
# 聲明 reduce(func,sequence[, initial]) -> value # func()是自定義函數,在其中實現對參數sequence即待處理序列的連續操作 # 參數initial可以省略,若不為空,則initial的值首先傳入func()進行計算。若sequence為空,則對initial的值進行處理 # reduce()返回值為func()計算后的結果
# 功能 def sun(x,y): return x+y from functools import reduce print (reduce(sum,range(0,10))) # 0加到9,結果45 print (reduce(sum,range(0,10),10)) # 10加0加到9,結果55 print (reduce(sum,range(0,0),10)) # 結果10
如果用reduce()進行累計計算,必須在sum中定義兩個參數,分別對應加法運算符兩側的操作數。
- map()
可對多個序列的每個元素都執行相同的操作,並返回一個map對象。
# 聲明 class map(object) map(func, *iterables) --> map object # func自定義函數,實現對每個元素的操作 # iterables是待處理序列,其個數可以是多個 # map返回值為處理后的列表
若map中提供多個序列,則每個序列中元素一一對應計算。若長度不等,短的后補None
3.6dir()函數
你可以使用內建的dir函數來列出模塊定義的標識符。標識符有函數、類和變量。
當你為dir()提供一個模塊名的時候,它返回模塊定義的名稱列表。如果不提供參數,它返回當前模塊中定義的名稱列表。
import sys dir(sys) # 輸出sys模塊上的屬性列表。 ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdout__', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode', 'meta_path','modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version', 'version_info', 'warnoptions'] dir() # 返回當前模塊的屬性列表,輸入的模塊同樣是列表的一部分。 ['__builtins__', '__doc__', '__name__', 'sys'] a = 5 # create a new variable 'a' dir() ['__builtins__', '__doc__', '__name__', 'a', 'sys'] del a # delete/remove a name dir() ['__builtins__', '__doc__', '__name__', 'sys']
為了觀察dir的作用,定義一個新的變量a並且給它賦一個值,檢驗dir,在列表中增加了以上相同的值。
我們使用del語句刪除當前模塊中的變量/屬性,這個變化再一次反映在dir的輸出中。
PS:del語句在運行后被用來 刪除一個變量/名稱。在這個例子中,del a,你將無 法再使用變量a——它就好像從來沒有存在過一樣。
3.7自定義包
包就是一個至少包含_init_.py文件的文件夾。包為了實現程序的重用,把實現一個常用功能的代碼組合到一個包中,調用包提供的服務從而實現重用。
# 包的_init_.py程序 if _name_ == '_main_': print ('作為主程序運行') else: print ('pack初始化')
# 包的myModule模塊 def func(): print ("pack.myModule.func()") if _name_ == '_main_': print ('myModule作為主程序運行') else: print ('pack被另一模塊調用)
# main模板調用pack中的函數 from pack import myModule myModule.func() # output: pack初始化 myModule被另一個模板調用 pack.myModule.func()
_init_.py也可用於提供當前包的模塊列表。eg.在pack包的_init_.py文件前添加一行代碼
_all_ = ["myModule"]
_all_用於記錄當前pack包所含的模板。其中方括號中的內容是模板名的列表,如果模塊數量超過2個,使用逗號分開。
這樣就可以在main模板中一次導入pack包中的所有模塊。
from pack import * myModule.func() # 首先執行pack包的_init_.py文件,然后在屬性中查找pack包含有的模塊。如果pack包的_init_.py文件不適用_all_屬性記錄模塊名,main模塊調用時將不能識別myModule模塊。Python將提示如下錯誤: NameError:name 'myModule' is not defend