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。
img

2.呼叫test()函式。
img

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

img

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

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

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

函式內的變數,是屬於區域變數,離開函式無法再讀取,因為函式的記憶體位址在離開函式時已被清除。

相同的函式名

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的記憶體位址。
img

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

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

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

不同函式之間的參數傳遞,是用「複製」記憶體位址的方式,把複製的記憶體位址指派給函式中的變數。

完整程式碼:

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

results matching ""

    No results matching ""