第九章:Python的函數functionpython
---------------------------------<習題18&19:命名、變量、代碼、函數>------------------------------bash
除了Python自帶的函數外,你還能夠在Python環境下定義本身的函數,沒錯,是能夠創造本身的函數。這個函數能夠接受參數,方式跟咱們前面學到的同樣,能夠用raw_input()或argv。less
命令def:它的意思是「定義define」,如同定義變量同樣,定義函數也是用「def」這個命令;ide
在def後面,空一格,而後鍵入函數的名稱(你能夠自由選擇,但最好是能體現函數的功能,和變量的取名同樣,不能用數字,但能夠用字幕開頭的名字,例如a1),再而後用「冒號:" 來收尾,表面下面的內容是該函數的內容;冒號後另起一行,須要使用4個空格縮進,表示縮進的代碼是被包含在上面定義的函數內部。函數
下面展現書中四個函數的例子,ex18.py的代碼以下:ui
1 #-*-coding:utf-8-*- 2 3 # this one is like your scripts with argv 4 def print_two(*args): #def 是命令define的縮寫,定義的意思。此處用來定義一個函數print_two(), 5 #後面的冒號,表示冒號後面的內容,是該函數的內容,即該函數是一個輸出字符串的函數 6 arg1, arg2 = args 7 print "arg1: %r, arg2: %r" % (arg1, arg2) 8 9 # ok, that *args is actully pointless, we can just do this 10 def print_two_again(arg1, arg2): #相對於第一個函數,沒有使用參數解包的過程, 11 #而是直接在函數的括號內輸入變量名 12 print "arg1: %r, arg2: %r" % (arg1, arg2) 13 14 # this just takes one argument 15 def print_one(arg1): 16 print "arg1: %r" % arg1 17 18 # this one takes no arguments 19 def print_none(): 20 print "I got nothing'." 21 22 23 # 下面四行代碼,是爲了運行上面的四個函數,直接鍵入函數的名稱,並在函數的括號內寫入該函數的參數便可 24 print_two("Zed", "Shaw") 25 print_two_again("Zed", "Shaw") 26 print_one("First!") 27 print_none()
終端運行結果以下:this
注意:請必定要將函數相關的定義和使用弄清楚,由於可能會跟後嗎學到的「類class」弄混,我如今也不能完徹底全地講出這兩則的區別,但願再學到「類class」的時候會弄清楚,屆時會針對函數和類的區別作一個解釋spa
在習題19中,書中講到幾種函數的參數傳遞方式,ex19.py代碼以下:命令行
1 #-*-coding:utf-8-*- 2 def cheese_and_crackers(cheese_count, boxes_of_crackers): 3 print "You have %d cheeses!" % cheese_count 4 print "You have %d boxes of crackers!" % boxes_of_crackers 5 print "Man that's enough for a party!" 6 print "Get a blanket.\n" 7 8 9 print "We can just give the founction numbers directly:" 10 cheese_and_crackers(20, 30) #直接用數值賦予函數的輸入 11 12 13 print "OR, we can use variables from our script:" 14 amount_of_cheese = 10 #該變量在此時賦予的數值,可運用於其它相同的變量名的值, 15 amount_of_crackers = 50 #該變量在此時賦予的數值,可運用於其它相同的變量名的值, 16 17 cheese_and_crackers(amount_of_cheese, amount_of_crackers) #利用已被賦予數值的變量,做爲函數的輸入 18 19 20 print "We can even do math inside too:" 21 cheese_and_crackers(10+20, 5+6) #能夠用算式做爲函數的輸入 22 23 24 print "And we can combine the two, variables and math:" 25 cheese_and_crackers(amount_of_cheese +100, amount_of_crackers + 1000) #能夠用字符串和數字的和,做爲函數的輸入參數
終端運行結果以下:3d
我本身也用兩種不一樣的方式,完成函數參數的傳遞:raw_input()和argv
ex19_2.py用的是raw_input(), 我就不在貼上終端運行結果了:
1 # -*-coding:utf-8-*- 2 # 很差意思,我在辭職以前,是建築公司的一名電氣工程師,平時會涉及到電纜cable數量的統計工做,因而 3 # 就寫了下面這個腳本。 4 5 print "we can use raw_input() for inputing all the arguments" 6 print "Now you can type in your arguments" 7 8 print "How many zones there are ?" 9 zones = int(raw_input()) #將輸入的str強制轉換成int,與第25行的變量要求一致 10 11 print "How many levels each zones?" 12 levels = int(raw_input()) 13 14 print "How many layouts in each levels?" 15 layouts = int(raw_input()) 16 17 print "How many types of cables in each layouts?" 18 types = int(raw_input()) 19 20 print "The quantity of each kind of cable:" 21 quantities = int(raw_input()) 22 23 def len_cables(zones, levels, layouts, types, quantities): 24 # 函數名和函數的參數的定義,注意括號和最後的冒號 25 length_cables = zones * levels * layouts * types * quantities 26 print "There are %d zones in project Thalassa" % zones 27 print "Each zone has %d levels" % levels 28 print "Each level has %d layouts" % layouts 29 print "Each layout has %d types of cables" % types 30 print "Each type of cables has %d meters" % quantities 31 print "The length of cables equals %d" % length_cables 32 # 函數的參數必須是4個空格的縮進 33 34 35 len_cables(zones, levels, layouts, types, quantities)
ex19_3.py用的是argv,值得注意的是,這裏函數的參數的類型和變量的類型產生衝突,爲了解決,我使用了int()將字符串強制轉換成數值類型,詳情見代碼:
1 # -*-coding:utf-8-*- 2 3 print "We can use argv to input the arguments:" 4 5 from sys import argv 6 7 name, zones, levels, layouts, types, quantities = argv 8 9 10 11 def len_cables(zones, levels, layouts, types, quantities): 12 # 函數名和函數的參數的定義,注意括號和最後的冒號 13 length_cables = int(zones) * int(levels) * int(layouts) * int(types) * int(quantities) 14 15 print "the name of project is %s" %name # 由於輸出的是字符串,因此不能用%d,而應該用%r或%s 16 print "There are %r zones in project Thalassa" % zones 17 print "Each zone has %r levels" % levels 18 print "Each level has %r layouts" % layouts 19 print "Each layout has %r types of cables" % types 20 print "Each type of cables has %r meters" % quantities 21 print "The length of cables equals %r" % length_cables 22 # 函數的參數必須是4個空格的縮進 23 24 len_cables(zones, levels, layouts, types, quantities) 25 26 #由於在第13行中,各個參數的的乘積獲得變量length_cables的定義,所以length_cables的輸出應該是數字,而非字符串 27 #可是在第24行中,雖然咱們在輸入這些參數時候輸入的是數字,可是系統默認爲其屬性是字符串 28 #所以關於這5個參數的定義,在第13行和第24行產生衝突, 29 #會出現TypeError: can't multiply sequence by non-int of type 'str' 30 #因此在第13行,給每個參數強制轉換成int,而非str
---------------------------------------<習題20:函數和文件>-----------------------------------
這個習題講的是將函數和文件的讀取結合起來。除此以外,還有一個很重要的命令:f.seek(1, 0):
# f.seek(p,0) 將指針移動當文件第p個字節處,絕對位置
# f.seek(p,1) 將指針移動到相對於當前位置以後的p個字節
# f.seek(p,2) 將指針移動到相對文章尾以後的p個字節
我準備的待讀取文件ex20_sample.txt以下:
1 "I don't know what's in her mind." 2 'Maybe I am the the unimportant one.' 3 'It does not change anything with me or not.' 4 'So I should put myself in the right position.' 5 'Also about my demands.'
見ex20.py的代碼:
1 #-*-coding:utf-8-*- 2 3 from sys import argv # 從sys軟件包中調取參數變量argv使用 4 5 script, input_file = argv # argv解包 6 7 def print_all(f): # 定義函數print_all(),f僅僅是個變量的名字 8 print f.read() # 函數的內容是輸出文本f的內容 9 10 def rewind(f): # 定義函數rewind(f),f僅僅是個變量的名字 11 f.seek(1,0) # 該函數的做用以下:1表示從文本開始的第1個字節的位置。 12 # 這個數字隻影響第一個line_count的位置 13 # f.seek(p,0) 將指針移動當文件第p個字節處,絕對位置 14 # f.seek(p,1) 將指針移動到相對於當前位置以後的p個字節 15 # f.seek(p,2) 將指針移動到相對文章尾以後的p個字節 16 17 18 def print_a_line(line_count, f): # 定義函數print_a_line 19 print line_count, f.readline() #即爲輸出該行在文本中是第幾行,並且把該行讀出來 20 #此處的line_count與下面的current_line是函數print_a_line的第一個參數,line_count只起到象徵做用 21 #而下面的current_line是通過定義的 22 #readline()函數返回的內容中包含文件原本就有一個\n,而print在打印時又會添加一個\n,這樣就會多一出一個空行, 23 #解決方法是在print語句結尾加一個逗號 24 25 current_file = open(input_file) # 定義current_file,爲何在argv的時候不用同樣的變量名呢? 26 # 由於input_file僅僅是個參數,其屬性是一個文本的名稱(字符串),而current_file是個變量,其屬性爲一個txt文本 27 28 print "First let's print the whole file:\n" 29 30 print_all(current_file) 31 print "-" * 30 32 33 print "Now, let's rewind, kind of like a tape." 34 35 rewind(current_file) 36 37 print "Let's print five lines:" 38 39 40 current_line1 = 1 #定義第一個current_line的值爲1,表示文本的第一句話前面標註「1」 41 print_a_line(current_line1, current_file) 42 43 current_line2 = current_line1 + 2 #定義第二個current_line的值爲第一個current_line +2, 44 #表示文本的第一句話前面標註「1」 45 print_a_line(current_line2, current_file) 46 47 current_line3 = current_line2 + 1 48 print_a_line(current_line3, current_file) 49 50 current_line4 = current_line3 + 1 51 print_a_line(current_line4, current_file) 52 53 current_line5 = current_line4 + 1 54 print_a_line(current_line5, current_file)
終端運行結果以下:
在ex20.py的最後一段代碼,是打印輸出文件的每一行,我在第八章裏的ex15_3.py腳本也用4種方法達到一樣的效果,可是源代碼裏面比較複雜,我將它改善了,見代碼ex20_1.py:
1 #-*-coding:utf-8-*- 2 3 from sys import argv # 從sys軟件包中調取參數變量argv使用 4 from sys import exit 5 6 script, input_file = argv # argv解包 7 8 def print_all(f): # 定義函數print_all(),f僅僅是個變量的名字 9 print f.read() # 函數的內容是輸出文本f的內容 10 11 def rewind(f): # 定義函數rewind(f),f僅僅是個變量的名字 12 f.seek(1,0) # 該函數的做用以下:將指針放到第一個字節的位置。1表示從文本開始的第1個字節的位置。 13 # 這個數字隻影響第一個line_count的位置 14 # f.seek(p,0) 將指針移動當文件第p個字節處,絕對位置 15 # f.seek(p,1) 將指針移動到相對於當前位置以後的p個字節 16 # f.seek(p,2) 將指針移動到相對文章尾以後的p個字節 17 18 19 def print_a_line(line_count, f): # 定義函數print_a_line 20 print line_count, f.readline() #即爲輸出該行在文本中是第幾行,並且把該行讀出來 21 #此處的line_count與下面的current_line是函數print_a_line的第一個參數,line_count只起到象徵做用 22 #而下面的current_line是通過定義的 23 #readline()函數返回的內容中包含文件原本就有一個\n,而print在打印時又會添加一個\n,這樣就會多一出一個空行, 24 #解決方法是在print語句結尾加一個逗號 25 26 current_file = open(input_file) # 定義current_file,爲何在argv的時候不用同樣的變量名呢? 27 # 由於input_file僅僅是個參數,其屬性是一個文本的名稱(字符串),而current_file是個變量,其屬性爲一個txt文本 28 29 print "First let's print the whole file:\n" 30 31 print_all(current_file) 32 print "-" * 30 33 34 print "Now, let's rewind, kind of like a tape." 35 36 rewind(current_file) 37 38 print "-"*30 39 40 41 42 print "Let's print five lines:" 43 def line(current_line): 44 45 while current_line <=4: #此處的變量current_line默認已經被定義 46 47 current_line = current_line + 1 48 print "This is No%r line:" % current_line 49 print_a_line(current_line, current_file) 50 51 line(current_line) 52 else: 53 exit(0) 54 55 line(0)
終端運行結果以下:
---------------------------------------<習題21&24:函數和文件>-----------------------------------
我在網上查了不少關於命令return的原理,可是都沒有看的很明白。我本身的理解是:return命令將某個值或者變量返回,供用戶隨時調用,例如將函數的結果定義成一個變量。
你們先看一下ex21.py的代碼:
1 #-*-coding:utf-8-*- 2 3 def add(a, b): 4 print "ADDING %d + %d" %(a, b) # 該命令行只是解釋函數的內容是什麼 5 return a + b #該命令行是函數實際的輸出結果 ,在該函數外就能夠調取該結果,其形式爲add(a, b) 6 # 以上兩行統必定義了函數add 7 8 def subtract(a, b): 9 print "SUBTRACTING %d - %d" % (a, b) 10 return a - b 11 12 def multiply(a, b): 13 print "MUTIPLY %d * %d" %(a, b) 14 return a * b 15 16 def divide(a, b): #不要忘記了冒號 17 print "DIVIDING %d / %d" %(a, b) 18 return a / b 19 20 21 print "Let's do some math wiht just fonctions." 22 23 age = add(30, 5) 24 height = subtract(78, 4) 25 weight = multiply(90, 2) 26 iq = divide(100, 2) 27 28 29 print "Age: %d, Height: %d, Weight: %d, IQ: %d" %(age, height, weight, iq) 30 31 32 # A puzzle for the extra credit, type it in anyway. 33 print "Here is a puzzle." 34 35 what = add(age, subtract(height, multiply(weight, divide(iq, 2)))) 36 37 print "That becomes:" , what, "Can you do it by hand?" 38 # 也能夠不用強制轉換符%,輸出變量what的值。若是使用%, 變量前面的逗號須要刪除
終端運行結果以下:
關於return的命令,我本身寫了一個代碼,可供參考:
1 #-*-coding:utf-8-*- 2 # 用到return的 3 def add(a, b): 4 return a + b 5 6 print add(2, 3) #不須要再運行函數,此時的add(2, 3)就是一個變量,直接能夠打印輸出的結果爲5 7 8 9 # 未用到return的 10 def add2(a, b): 11 c = a + b 12 print c 13 add2(2, 3) # 須要運行一下函數,在函數內部,已經有了打印輸出的命令
下面介紹一下習題24,一個比較特殊的地方:介紹函數返回多個數值時,這些數值如何被從新定義和被調用:
1 #-*-coding:utf-8-*- 2 print "Let's practice everthing!" 3 print 'You\'d need to know \'bout escapes with \\ that do \n newlines and \t tabs.' 4 5 poem = """ 6 \tThe lovely world 7 with logic so firmly planted 8 cannot discern \n the needs of love 9 nor comprehend passion from institution 10 and requires an explantation\n\t\twhere there is none. 11 """ 12 # 一個\t表示空出8位; 13 print "----------" 14 print poem 15 print "----------" 16 17 five = 10 - 2 + 3 - 6 18 print "This should be five :%s" % five 19 20 def secret_formula(started): 21 jelly_beans = started * 500 22 jars = jelly_beans / 1000 23 crates = jars / 100 24 return jelly_beans, jars, crates 25 26 27 28 start_point = 10000 29 beans, jars, crates = secret_formula(start_point) 30 #該命令行是爲了將函數 secret_formula(start_point)的三個返回值定義給三個變量jelly_beans, jars, crates 31 # 此處的beans等於上面的jelly_beans,不是由於名字類似,而是由於從新定義了函數secret_formula的第一個返回值 32 # 同理可知,第二個和第三個的參數,也是對應的,在此處能夠隨便更改 33 34 print "\t\tWith a starting point of : %d" %start_point 35 print "We'd have %d beans, %d jars, and %d crates." %(beans, jars, crates) #調用函數的返回值 36 37 start_point = start_point / 10 38 39 print "We can also do that this way:" 40 print "We'd have %d beans, %d jars, and %d crates.." % secret_formula(start_point)# 該方法也能夠調用函數的返回值 41 # 能夠用這個方法,%函數名,便可轉換函數的返回值
--------------------------------------<習題25:在終端直接調用函數>----------------------------------
咱們以前講的這麼多習題,都是用TextWrangler編輯好Python腳本,而後在終端裏輸入「python ex.py"來運行該腳本。其實咱們能夠在終端路直接調用某個腳本中的函數,在介紹如何操做以前,先介紹幾個比較特殊的函數:split(), pop(), sorted()。它們的功能,在ex25.py中有很是詳細的介紹:
例如 ex25.py代碼以下:
1 #-*-coding:utf-8-*- 2 # 用腳本編寫函數,寫出的函數,在python環境下能夠調用 3 def break_words(stuff): 4 """This function will break up words for us.""" # 這段命令行,爲「幫助文檔」,在python運行時,執行help(ex25) 5 # 或者help(ex25.break_words)會顯示出來,起到註釋的做用 6 words = stuff.split(' ') # split命令,能夠將對象分離,形式是'1’,‘2’ 7 return words # 返回words的值,用於調用 8 9 def sort_words(words): #是一個給句子排序的命令 10 """Sorts the words.""" 11 return sorted(words) 12 13 def print_first_word(words): 14 """Prints the first word after popping it off.""" 15 word = words.pop(0) # pop()函數用於移除列表中的一個元素(默認爲最後一個元素),而且返回該元素的值 16 # 0 表示是列表中的第一個元素,1 表示第二個,以此類推,最後一個也能夠用-1 17 print word # 此處返回的第一個元素,還是第一個函數中返回的列表words中的第一個元素,由於第二個函數中的words未用return返回 18 # 運行完上函數後,序列words的第一個元素ALl被刪除掉了 19 20 def print_last_word(words): 21 """Prints the last word after popping it off.""" 22 word = words.pop(-1) 23 print word # 此處返回的最後一個元素,還是第一個函數中返回的列表words中的最後一個元素,由於第二個函數中的words未用return返回 24 # 運行完上函數後,序列words的最後一個元素wait被刪除掉了,第一個元素All在上一個函數中刪除了 25 26 def sort_sentence(sentence): 27 """Takes in a full sentence and returns the sorted words.""" 28 words = break_words(sentence) 29 return sort_words(words) 30 31 def print_first_and_last(sentence): 32 """Prints the first and last words of the sentence.""" 33 words = break_words(sentence) 34 print_first_word(words) 35 print_last_word(words) 36 37 def print_first_and_last_sorted(sentence): 38 """Sorts the words then prints the first and last one.""" 39 words = sort_sentence(sentence) 40 print_first_word(words) 41 print_last_word(words)
終端運行結果以下:注意下方的截屏擡頭是「python」,而以前全部的截屏擡頭都是「bash」
截屏沒法解釋在python環境下鍵入的每一行代碼的含義,下方是我在TextWrangler把終端運行結果又解釋了一下,供參考:
1 #下面是在bash環境下運行python: 2 3 # >>> import ex25 該命令是在python中調用腳本ex25,在python環境下,不須要帶.py的後綴。 4 # >>> sentence = "All good things come to those who waits!" 5 # >>> words = ex25.break_words(sentence) 調用ex25中的第一個函數,對象是上面定義的sentence。這段命令 6 #中的ex25.break_words()中的「.」是爲了告訴python:」嗨, 7 #,我要運行ex25裏面的那個交break_words()的函數 8 # >>> words :是輸入變量words, 即在python環境下,打印出ex25.break_words()的返回值words 9 # ['All', 'good', 'things', 'come', 'to', 'those', 'who', 'waits!'] 10 # >>> sorted_words = ex25.sort_words(words) 是在python環境下定義變量sorted_words供後面使用 11 # >>> sorted_words 12 # ['All', 'come', 'good', 'things', 'those', 'to', 'waits!', 'who'] 13 # >>> ex25.print_first_word(words) 14 # All 15 # >>> ex25.print_last_word(words) 16 # waits! 17 # >>> wrods 18 # Traceback (most recent call last): 19 # File "<stdin>", line 1, in <module> 20 # NameError: name 'wrods' is not defined 21 # >>> words 22 # ['good', 'things', 'come', 'to', 'those', 'who'] 23 # >>> ex25.print_first_word(sorted_words) 此處的sorted_words並不在腳本當中,可是在python環境下已經定義, 24 # sorted_words = ex25.sort_words(words) 25 # All 26 # >>> ex25.print_last_word(sorted_words) 27 # who 28 # >>> sorted_words 29 # ['come', 'good', 'things', 'those', 'to', 'waits!'] 30 # >>> sorted_words = ex25.sort_sentence(sentence) 31 # >>> sorted_words 32 # ['All', 'come', 'good', 'things', 'those', 'to', 'waits!', 'who'] 33 # >>> ex25.print_first_and_last(sentence) 34 # All 35 # waits! 36 # >>> ex25.print_first_and_last_sorted(sentence) 37 # All 38 # who
以上即是對Python函數的介紹,有不清楚之處,還請見諒,本人能力有限!
第十章預告:邏輯關係、布爾表達式、if/elif/else語句、循環for語句、while語句、列表及其相關