在 Python 中使用 def 關鍵字來定義函數,和變數一樣每個函數也有一個名字,而且命名規則跟變數一樣。在函數名後面的括號中可以放置傳遞給函數的參數,而函數執行完成後通過 return 關鍵字來返回值。
在 Python 中,函數的參數可以有默認值,也支持使用可變參數。
給兩個函數的參數都設定了默認值,表示如果在調用函數的時候如果沒有傳入對應參數的值時將使用該參數的默認值。
from random import randint
def roll_dice (n = 2):
total = 0
for _ in range (n): # 搖n個骰子
total += randint(1 , 6)
return total
def add (a = 0, b = 0, c = 0):
return a + b + c
print(roll_dice()) # 如果沒有指定參數那麼使用默認值搖兩顆色子
print(roll_dice(3)) # 搖三顆色子
print(add())
print(add(1))
print(add(1 , 2))
print(add(1 , 2 , 3))
print(add(c = 50, a = 100, b = 200)) # 傳遞參數時可以不按照設定的順序進行傳遞
我們可能會對 0 個或多個參數進行加法運算,在不確定參數個數的時候,我們可以使用可變參數。
def add (* args): # 在參數名前面的 * 表示 args 是一個可變參數
total = 0
for val in args:
total += val
return total
# 調用 add 函數時可以傳入 0 個或多個參數
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
print(add(1, 3, 5, 7, 9))
在同一個 .py 文件中定義了兩個同名函數,由於 Python 沒有函數重載的概念,那麼後面的定義會覆蓋之前的定義,代表兩個同名函數實只有一個是存在的。
避免這種情況發生,使用函數的時候我們通過 import 關鍵字導入指定的模組就可以區分到底要使用的是哪個模組中的函數。Python 中每個文件就代表了一個模組,我們在不同的模組中可以有同名的函數。
module1.py
def foo():
print(' hello, world! ')
module2.py
def foo():
print(' goodbye, world! ')
區分方式有下列幾種方式
from module1 import foo
foo() # 輸出hello, world!
from module2 import foo
foo() # 輸出goodbye, world!
import module1 as m1
import module2 as m2
m1.foo()
m2.foo()
如果是下列這種方式,調用的是最後導入的那個 foo,所以後導入的 foo 會覆蓋前導入的 foo,則輸出 goodbye, world!
from module1 import foo
from module2 import foo
foo() # 輸出 goodbye, world!
當導入的模組除了定義函數之外還有其他可以執行的程式碼,在導入這個模組時將會執行程式碼,但如果不希望他執行其他程式碼,我們可以將這些執行程式碼利用 name == main ,name 是 Python 中一個隱含的變數,它代表了模組的名字, main 是被 Python 直接執行的模組的名字。這樣的話除非直接運行該模組,if 條件下的這些程式碼是不會執行的。
module3.py
def foo():
pass
def bar():
pass
if __name__ == ' __main__ ' :
print('call foo()')
foo()
print('call bar()')
bar()
test.py
import module3
# 導入 module3 時不會執行模組中 if 條件成立時的代碼
# 因為模組的名字是 module3 而不是 __main__
練習1 - 實現計算求最大公因數和最小公倍數的函數。
def gcd (x, y):
if x > y:
x, y = y, x
for factor in range (x, 0, -1):
if x % factor == 0 and y % factor == 0:
return factor
def lcm (x, y):
return x * y // gcd(x, y)
練習2 - 實現判斷一個數是不是回文數的函數。
def is_palindrome (num):
temp = num
total = 0
while temp > 0:
total = total * 10 + temp % 10
temp //= 10
return total == num
練習3 - 實現判斷一個數是不是質數的函數。
def is_prime (num):
for factor in range (2, num):
if num % factor == 0:
return False
return True if num != 1 else False
練習4 - 判斷輸入的正整數是不是回文質數。
def is_palindrome (num):
temp = num
total = 0
while temp > 0:
total = total * 10 + temp % 10
temp //= 10
return total == num
def is_prime (num):
for factor in range (2, num):
if num % factor == 0:
return False
return True if num != 1 else False
if __name__ == '__main__' :
num = int(input('請輸入正整數: '))
if is_palindrome (num) and is_prime (num):
print('%d 是回文質數' % num)
else:
print('%d 不是回文質數' % num)
def foo():
b = 'hello'
def bar():
c = True
print(a)
print(b)
print(c)
bar()
if __name__ == '__main__':
a = 100
foo()
上面的程式碼 if 中定義變數 a,這是一個全域變數(global variable),屬於全局作用域,因為它沒有定義在任何一個函數中。
上面的 foo 函數中定義變數 b,這是一個定義在函數中的區域變數(local variable),屬於局部作用域,在 foo 函數的外部並不能訪問它。
對於 foo 函數內部的 bar 函數來說,變數 b 屬於嵌套作用域,在 bar 函數們可以訪問到它。
bar 函數中的變數 c 屬於局部作用域,在 bar 函數之外是無法訪問的。
def foo():
a = 200
print(a) # 200
if __name__ == '__main__':
a = 100
foo()
print(a) # 100
def foo():
global a
a = 200
print(a) # 200
if __name__ == '__main__':
a = 100
foo()
print(a) # 200
上面兩段程式碼的差異在於 global 關鍵字,foo 函數中的變數 a 加上 global 變成全局作用域。
變數 a 在全局作用域中,只要出現變數 a 則其定義就會改變。
如果希望函數內部的函數能夠修改嵌套作用域中的變數,可以使用 nonlocal 關鍵字來指示變數來自於嵌套作用域。