function
語法
宣告函式由def開始,後面是函式名,然後圓括號(),圓括號裡面可以有參數,也可以沒有參數。
圓括號後面有冒號:,函式的程式碼從冒號之後開始。
使用縮排來撰寫函式中的程式碼。
有參數
def 函式名(參數1, 參數2...):分號
程式碼
無參數
def 函式名():
程式碼
函式命名不能用數字跟-開頭。
以下都會產生錯誤。
1
2
3
4
def 1test():
print("test")
def -test():
print("test")
函式傳回值
無return
def 函式名(參數1, 參數2...):
程式碼
函式若沒有return,會有隱藏的return None
None也是一個類型,代表「空」,但有自己的記憶體位址。
1
2
3
4
5
6
def test():
print("test")
result = test()
print("type of result = ",type(result))
print("result = ", result)
print("address = ", id(result))
test
type of result = <class 'NoneType'>
result = None
address = 4510668496
有return
def 函式名(參數1, 參數2...):
return 程式碼
1
2
3
4
5
6
7
8
def max(a, b):
if a > b:
return a
else:
return b
n = max(10, 5)
print(n)
10
多個傳回值
1
2
3
4
5
6
def get_info(a, b):
return a + b, a - b
r1, r2 = get_info(100, 20)
print(f"r1: {r1}, r2: {r2}")
r1: 120, r2: 80
函式全域變數 區域變數
函式內宣告的區域變數,函式之外不能使用。
以下程式碼編譯失敗。
1
2
3
4
5
def fun1():
x = 50
print(f"x = {x}")
print(f"x = {x}")
全域變數是n。
fun1自己宣告區域變數n,跟全域變數n是二個獨立個體,不相同。
不會修改到全域變數的n的內容。
1
2
3
4
5
6
7
8
n = 100
def fun1():
n = 50
print(f"fun1() n = {n}")
fun1()
print(f"outside n = {n}")
fun1() n = 50
outside n = 100
如果要修改函式外部的全域變數,函式內要使用global。
1
2
3
4
5
6
7
8
9
n = 100
def fun1():
global n # 使用global 變數名
n = 50
print(f"fun1() n = {n}")
fun1()
print(f"outside n = {n}")
fun1() n = 50
outside n = 50
函式參數
函式參數傳遞 記憶體位址
呼叫函式後,記憶體會開立一個「新的」Stack空間,跟主程式main的stack空間分開來。
如果參數是基本型別(int, float),而不是list、tuple……等等類型,
函式是把傳進來的「記憶體位址」,複製給函式參數。
以下的程式碼執行結果為55,也就是函式中即便修改a參數為10,也不影嚮主程式的n,參數a跟變數n都在各別不同的Stack。
1
2
3
4
5
def test(a):
a = 10
n = 55
test(n)
55
1.先執行主程式n=55,在Stack堆疊區中,建立新的Stack,n的變數存的是0x0011,Memory中的Heap區,0x0011記憶體位址存的是55。

2.呼叫test()函式。

3.執行到test(a)函式後,在Stack堆疊區中,建立新的Stack,Stack建立方式由下至上。
a的變數存的是0x0011。

4.a=10,會把變數a存0x0022的記憶體位址,0x0022記憶體位址存的是10。

5.test()函式執行完畢後,test函式的Stack會被清除,stack記憶體位址會被記憶體回收,供之後其它變數使用。

6.主函式main()執行完畢後,主函式main()的Stack會被清除,stack記憶體位址會被記憶體回收,供之後其它變數使用。

函式內的變數,是屬於區域變數,離開函式無法再讀取,因為函式的記憶體位址在離開函式時已被清除。
相同的函式名
Python可以有相同的函式名,執行函式時,執行離上方自己近的函式,不是下方。
1
2
3
4
5
6
7
def test():
print("1")
def test():
print("2")
test()
2
1
2
3
4
5
6
7
8
def test():
print("1")
test()
def test():
print("2")
test()
1
2
呼叫的函式參數不一致
Python函式沒有多型,以下程式碼,執行test(),它不會去配對參數的數量,Python會執行離自己最近的同名函式test(x)。
就會產生參數數量無法配對的Error。
1
2
3
4
5
6
7
8
def test():
print("1")
test()
def test(x):
print("2")
test()
TypeError: test() missing 1 required positional argument: 'x'
函式參數沒有類型
因為參數沒有類型,所以預期是字串的參數,呼叫函式時把參數設為int、float也是可以的。
1
2
3
4
def get_info(name, price):
print(f"name: {name}, price: {price}")
get_info(55, "Mary")
name: 55, price: Mary
參數預設值
可以為參數指派預設值,但有預設值的參數要放在後面。
如果參數有預設值,呼叫函式時,可以不用傳入參數。
1
2
3
4
5
def get_info(produt_name, price=10):
print(f"produt_name = {produt_name}, price = {price}")
get_info("Cookie")
produt_name = Cookie, price = 10
以下會編譯失敗,因為有預設值的參數要放在後面,但在下面程式碼,卻放在前面。
1
2
def get_info(produt_name = "Cookie", price):
print(f"produt_name = {produt_name}, price = {price}")
可變參數
參數數量不固定,可能有0個參數、1個參數,也可能有多個參數。
參數的數量為0至多個參數,會把多個參數存入tuple。
參數名使用*星號開頭,如下面程式碼,使用*args作為可變參數。
語法
def sum(*args):
程式碼
以下程式碼,{args}直接輸出tuple的內容,使用type()輸出類型是tuple。
1
2
3
4
def get_info(*args):
print(f"args: {args} , type: {type(args)}")
get_info("Cookie", "Bread", "Fish")
args: ('Cookie', 'Bread', 'Fish') , type: <class 'tuple'>
使用for可以把tuple的元素一個一個輸出。
1
2
3
4
5
def get_info(*args):
for arg in args:
print(arg)
get_info("Cookie", "Bread", "Fish")
Cookie
Bread
Fish
可以使用[索引]取出個別元素:
1
2
3
4
5
6
7
8
9
10
11
12
13
def getInfo(*args):
if len(args) == 1:
print(args[0])
elif len(args) == 2:
print(args[0], args[1])
else:
for arg in args:
print(arg, ",", end="")
getInfo("Hello")
getInfo("abc", "def")
getInfo(1, 2, 3, 4, 5)
Hello
abc def
1 ,2 ,3 ,4 ,5 ,
使用return把傳回值傳入result的變數中。
1
2
3
4
5
6
7
8
def sum(*args):
total =0
for arg in args:
total += arg
return total
result = sum(1,2,3,4,5,6,7,8,9)
print(result)
*args為0至多個參數,若無任何參數,也可以。
以下程式碼呼叫sum()是不代入任何參數。
1
2
3
4
5
6
7
8
def sum(*args):
total =0
for arg in args:
total += arg
return total
result = sum()
print(result)
0
key與value的參數
參數的組成為key與value,此處key的命名仍要符合變數命名規範,不能數字開頭。
呼叫函式(key1 = value1, key2 = value2, key3 = value3, key4 = value4)
info(name="Mary", age=18)
傳入的參數key與value會變成dict的資料型態。
使用二個星星**代表參數是key與value。
語法
def info(**args):
程式碼
1
2
3
4
5
6
7
def info(**args):
print(f"args: {args}, type: {type(args)}")
for key in args:
print(f"{key}: {args[key]}")
info(name="Mary", age=18)
args: {'name': 'Mary', 'age': 18}, type: <class 'dict'>
name: Mary
age: 18
函式與字串Memory Model
Prerequisites:
1.在Stack建立main()的Stack,變數str1指向0x100的記憶體位址。

2.進入change()函式,把str1的記憶體位址0x100「複製」給str_param變數,讓str_param也指向0x100。

3.str_param變數指向0x200的記憶體位址。

4.執行完change()函式後,change函式被記憶體回收,相關的stack與str_param變數也清除掉。
main()函式中的str1仍是指向0x100的記憶體位址。

不同函式之間的參數傳遞,是用「複製」記憶體位址的方式,把複製的記憶體位址指派給函式中的變數。
完整程式碼:
1
2
3
4
5
6
7
def change(str_param):
str_param += "abc"
print(f"str_param: {str_param}")
str1 = "Hi"
change(str1)
print(f"str1: {str1}")
str_param: Hiabc
str1: Hi