Python基礎講義(三):函式初步
阿新 • • 發佈:2020-11-17
函式初步
0x01內容導圖
0x02函式定義
-
程式的本質:問題分解,逐步求精
-
基本原則:一個函式一個功能
-
函式定義語法:
def fun_name([args]): statements [return values]
-
函式名要有意義,提高可讀性;
- args:引數列表,相當於函式的輸入,定義時稱為形式引數;可以沒有引數
- return values:返回值,相當於函式的輸出(可以有多個返回值);可以沒有返回值
-
函式呼叫語法:function_name(args),圓括號不能省略;呼叫時,引數被稱為實際引數
程式碼示例(檔案方式,is_leap.py):判斷是否為閏年
#請熟練掌握下述框架,養成自頂向下的編碼習慣 def is_leap(year): return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0) def run(): year = int(input("please input a year:")) #輸入 flag = is_leap(year) #處理 print(f"{year}年是閏年:{flag}") #輸出 if __name__ == "__main__": #是否為主模組:直接執行該模組,則為主;其他方式,如被匯入,則不是 run()
說明:
- Python中語句塊以縮排表示歸屬,函式是語句塊,函式體必須縮排
- input函式是Python的標準輸入函式,從鍵盤讀入內容,返回字串形式;因此輸入數字的時候通常需要轉換函式
練習:
- 利用math庫,完成is_square(n)函式的定義,判斷n是否為完全平方數。
- 定義函式calc_area(w, h):計算長方形面積並返回
0x03變數作用範圍
-
定義在函式內的稱為區域性變數,只能在函式內訪問
-
定義在函式外的稱為全域性變數,儘量少用
- 函式內可讀訪問全域性變數
- 寫訪問,需要使用global語句宣告
- 同名解析:就近原則
-
locals()/globals()函式:區域性/全域性名稱空間
-
檢視函式:
- dir函式:顯示模組中定義的函式
- help函式:顯示函式的用法
程式碼示例(檔案方式,scope.py):
#========================測試一============================
def disp():
name = "world"
print("hello" + name)
print(name) #error,區域性變數,外面不能訪問
#========================測試二============================
#函式內可以讀訪問全域性變數
def test():
return x + y
x, y = 2, 3
test()
#========================測試三============================
def method():
x = 10 #賦值即定義,此處x為區域性變數
print(x) #就近原則,x為區域性變數
x = 5 #此處x為全域性變數
method()
print(x) #列印全域性變數x,其值仍為5
#========================測試四============================
def test2():
#global x
x += 1 #報錯,區域性變數未賦值就使用
print(x)
x = 5
test2()
print(x)
"""錯誤解析:展開x = x + 1,Python從左開始解析,第1次遇到x,由於出現在賦值號左邊,x被解釋為區域性變數(賦值即定義);繼續解析遇到第2個x,就近原則訪問區域性變數x,而這時x還未完成賦值,因此報錯。"""
#修改辦法:第16行取消註釋,將x宣告為全域性,然後才能修改x的值
0x04測試驅動開發
-
測試先行,結對編碼
- 對外介面設計:先思考函式怎麼用,會返回什麼結果,即測試用例設計
- 程式碼實現:讓測試通過
-
Python自帶測試庫:doctest
- 嵌入式:利用文件註釋(三引號註釋)
程式碼示例(閏年判斷為例):
def is_leap(year): """ 判斷year是否為閏年,用法如下: >>> is_leap(2000) True >>> is_leap(1998) False >>> is_leap(1900) False >>> is_leap(2020) True """ return year % 4 == 0 #故意實現錯誤 if __name__ == "__main__": import doctest doctest.testmod(verbose=True)
測試部分結果如下:
...
Failed example:
is_leap(1900)
Expected:
False
Got:
True
Trying:
is_leap(2020)
Expecting:
True
ok
1 items had failures:
1 of 4 in __main__.is_leap
4 tests in 2 items.
3 passed and 1 failed.
***Test Failed*** 1 failures.
上述結果顯示,我們的3個測試都通過了,但1900年測試失敗,不是閏年卻返回了是,程式碼實現應該和前面的例子相同,修改後再測試可以看到:
1 items passed all tests:
4 tests in __main__.is_leap
4 tests in 2 items.
4 passed and 0 failed.
Test passed.
- 獨立式:測試用例單獨用txt檔案儲存,程式碼和用例分開(儲存在同一目錄下)
程式碼示例(一元二次方程求解),測試檔案solve_equation_test_cases.txt如下:
>>> from solve_equation import *
>>> solve_equation(1, -2, 1)
(1.0, 1.0)
>>> solve_equation(1, 1, -6)
(2.0, -3.0)
>>> solve_equation(2, -1, -3)
(1.5, -1.0)
程式碼檔案solve_equation.py如下:
def solve_equation(a, b, c):
import math
delta = b*b - 4*a*c
delta = math.sqrt(delta)
x1 = (-b + delta) / (2*a)
x2 = (-b - delta) / (2*a)
return x1, x2
執行方式:命令列下,切換到對應目錄,然後執行命令python -m doctest -v solve_equation_test_cases.txt
,其執行結果如下:
Trying:
from solve_equation import *
Expecting nothing
ok
Trying:
solve_equation(1, -2, 1)
Expecting:
(1.0, 1.0)
ok
Trying:
solve_equation(1, 1, -6)
Expecting:
(2.0, -3.0)
ok
Trying:
solve_equation(2, -1, -3)
Expecting:
(1.5, -1.0)
ok
1 items passed all tests:
4 tests in solve_equation_test_cases.txt
4 tests in 1 items.
4 passed and 0 failed.
Test passed.
綜上,不管是嵌入式還是獨立式,使用doctest進行測試驅動開發,明顯的一個好處就是測試用例可以儲存,可以反覆進行測試,特別是我們修改程式碼的時候,可以保證之前通過的測試必須再通過。
0x05小結
- 理解模組化思想,熟練掌握函式定義語法
- 掌握變數的作用範圍
- 理解測試驅動開發,掌握doctest庫的使用