iT邦幫忙

2024 iThome 鐵人賽

DAY 10
1
Python

從概念到應用:Python實戰開發學習之旅系列 第 10

[Day9] 第二週 - 進階工程師的開端 - 函數(Function)

  • 分享至 

  • xImage
  •  

今日目標

https://ithelp.ithome.com.tw/upload/images/20240924/20121052PC9wB1xx52.png

根據前面的學習重點,我會分類成五個(如果有額外需要補充的會列在後面喔!!)

1.函數定義: 今天會解釋何謂函數?跟python定義的函數方式為何?
2.參數: 介紹什麼是參數值,如何應用?
3.作用域 : 介紹作用域的範圍跟使用場景。
4.重構: 重新定義過新的函示,也可以理解邏輯拆分。
5.返回: 解釋返回值得作用。

函數定義

1. 內建函數跟自訂函數

1.1內建函數
Python 自帶的函數,無需定義即可使用,這些函數通常用於處理常見的操作,如 print()、len()、sum() 等。
其實我們前面已經有接觸過了優~

numbers = [1, 2, 3]
print(len(numbers))  # 3 

# print() 函數可以把框框內的資料印出來。
# len() 函數可以計算List的長度。

tip. len() 也就是List有幾個元素,這時候就不是從0開始了喔!! 我們也很常用這個方式來控制迴圈次數

1.2自訂函數

https://ithelp.ithome.com.tw/upload/images/20240924/20121052XEy1mVqxTe.png

def function_name(argument):
    """
    Docstrings : this is basic function demo.
    """
    # 主要程式碼區域
    print(argument)

function_name("hello, this is basic input text")

# help(function_name)
print(function_name.__doc__)

透過程式碼跟圖片可以比較我們可以看到python中的函數定義
1.定義:def 是用來定義函數的關鍵字,告訴 Python 我們正在定義一個函數。
2.函數的名稱: 必須遵守 Python 的命名規則,如以字母開頭,並且不能使用保留字。函數名稱通常應具有描述性,以便能夠清楚了解其用途。 => 沒有強制要求名字但易懂或目的明確更可以在維護時更方便整理跟維護。

混淆: 你不太希望函數取名叫做def abc: 或是 def functionA 這個會讓維護的工程師很難協助除錯或查找
建議: 你可以取名叫做 def checkName: 或是 def callUserAPI

1.3.參數 (Parameters) : 參數是函數在被呼叫時接收的輸入值,用來處理函數內的操作。
補充1.參數可以有多個,也可以沒有參數。
補充2.參數(Arguments) 通常式呼叫function時代入的值

範例:


# Parameters
def greet(name):  # 'name' 是一個參數
    return f"Hello, {name}!"

# Arguments
name = "Alice"
greet(name)  # 呼叫函數時,傳入 "Alice" 作為參數

1.4.return 關鍵字:表示函數需不需要回傳值。
tips 通常在呼叫完別的函數,讓程式碼執行完的結果。 會透過新增一個變數,比如說:result= function() 來承接呼叫function計算後的結果

比如說:
1.我今天有10元美金,我想要換新台幣
2.可以透過changeNTD這個函數計算後來回傳值
3.可以透過變數myRealNTD來承接回傳值

def changeNTD(num):
    money = num *31
    return money

myRealNTD = changeNTD(10)

print(f"我換完錢之後的新台幣是:{myRealNTD}")

tips : print字串可以透過f"" ,引號字串裡面如果要包變數,需要透過f{}裡面大括號可以包變數

2. 參數值

2.1基本定義:
參數是傳遞給函數的輸入值,可以在函數內部使用。參數可以是位置參數、關鍵字參數、預設參數或可變長度參數

2.2位置參數 (Positional Arguments)定義:

定義:
位置參數是最常見的參數類型,根據它們在函數定義中的順序來傳遞。當調用函數時,必須按照定義時的順序提供相應的實際參數。

特點:
正確的順序傳遞
數量必須與形式參數的數量一致。

def calculate_area(width, height):
    return width * height

# 正確調用
area = calculate_area(5, 10)  # width=5, height=10
print(area)  # 輸出: 50

# 錯誤調用示例
# calculate_area(5)  # TypeError: missing 1 required positional argument: 'height'

如果少了一個參數,height就表示沒有東西可以給參數塞進去就會錯了喔!!

2.3關鍵字參數 (Keyword Arguments)定義:

關鍵字參數允許你在調用函數時使用參數名稱來指定實際值,這樣可以不按照位置順序傳遞參數

特點:
可以隨意排列關鍵字參數的順序。
增加了函數調用的可讀性。

def describe_pet(animal_type, pet_name):
    print(f"I have a {animal_type} named {pet_name}.")

# 使用關鍵字參數
describe_pet(pet_name="Buddy", animal_type="dog")  # 輸出: I have a dog named Buddy.

tips
1.從這邊可以看到,即便順序錯了也沒有關係
2.但如果想要不指明,第二個指明需要照順序describe_pet("Buddy", pet_name="dog")
3.不指明的時候,順序>指明。 其實也很好用邏輯推斷,如果位置對錯了那程式就會找不到正確參數

2.4預設參數 (Default Arguments)

定義:
預設參數是在函式定義時為某些參數指定的默認值。
特點:
可以使某些參數變為可選,簡化函式調用。

tips預設值必須放在位置參數之後。

def greet(name="Guest"):
    return f"Hello, {name}!"

# 使用預設值
print(greet())          # 輸出: Hello, Guest!
print(greet("Alice"))  # 輸出: Hello, Alice!

2.5可變長度參數 (Variable-Length Arguments)

定義:
可變長度參數允許函式接受任意數量的位置或關鍵字參數。使用 *args 表示可變位置參數,使用 **kwargs 表示可變關鍵字參數。

特點:
*args 將多餘的位置參數收集到一個元組(tuple)中。
**kwargs 將多餘的關鍵字參數收集到一個字典(dict)中。

tips
1.星星符號*加上任何變數名稱來定義可變長度的位置參數,這並不一定要叫做 *args。這只是 Python 社區中的一個慣例,方便開發者理解和使用。
2.兩個 **的kwarfs也是一樣的道理

*args的用法
下面範例就是要把一坨數字變成tuple丟進去裡面做總和。sum()可以把所有數字加總->跟數學的simga一樣~

def collect_numbers(*numbers):
    return sum(numbers)

result = collect_numbers(1, 2, 3, 4)
print(result)  # 輸出: 10

kwarfs的用法
就是dict的意思,可以看到是變數=值的方式丟進去

def print_info(**info):
    for key, value in info.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=30, city="New York")
# 輸出:
# name: Alice
# age: 30
# city: New York

3.作用域

基本定義:
作用域是指變量在程式中可見的範圍。Python 中主要有四種作用域:局部作用域、嵌套作用域、全局作用域和內建作用域。

使用場景:
在函數內部定義變量時,該變量只在該函數內部有效(局部作用域)。
使用全局變量時,可以在整個模組中訪問,但需注意修改全局變量時需要使用 global 關鍵字。

我們可以用視覺圖來呈現作用域的感覺。
https://ithelp.ithome.com.tw/upload/images/20240924/20121052XlrfVFjN3K.png

程式說明:

Step1全域變數:

ID_card = "roni" 是全域變數,這個變數會在整個程式中可見,不只限於某個函數或區域內部。

Step2函數 server_room:

這個函數內有一個區域變數 localArea,用來表示伺服器的認證區域 "server_auth"。

Step3內部函數 check:

check 函數負責檢查是否 ID_card 等於 "roni",如果正確則允許進入 localArea,並且輸出相應訊息。
如果 ID_card 不符合,則會顯示 "Access denied"。

Step4呼叫 server_room 函數:

當程式執行時,會呼叫 server_room(),而 server_room 內部的 check 方法會進行 ID 檢查並輸出結果。

# 全域變數
ID_card = "roni"

# 定義 function
def server_room():
    # 區域變數
    localArea = "server_auth"

    # 定義 check 方法來檢查 ID_card
    def check():
        if ID_card == "roni":
            print(f"{ID_card}, Access granted to {localArea}.")
        else:
            print("Access denied.")

    # 呼叫 check 方法進行檢查
    check()

# 呼叫 server_room 函數
server_room()

這個是一個很實際生活的例子
假設roni是這家公司的IT,那麼我們要檢查是否有權限
可以想像server room這個function是裡面的機房
local_area就是裡面機房的權限變數
check()就是檢查是否是roni,代表有權限可以進入/images/emoticon/emoticon01.gif

4.函式重構(Function Refactoring)

定義:是指在不改變程式功能的前提下,重新組織和修改函式內部的結構,使代碼更加簡潔、可讀性更高、可維護性更強。以下是重構的幾個重點:

4.1簡化函式
目的:減少函式的長度,讓每個函式只負責一個單一的任務(遵循單一責任原則)。
重點:將過於複雜或包含多個邏輯的函式拆分成多個小型、易於理解的函式,並讓每個函式專注於一件事情。

# Before refactoring
def process_data(data):
    total = 0
    for d in data:
        total += d
    avg = total / len(data)
    return avg

# After refactoring
def calculate_total(data):
    return sum(data)

def calculate_average(data):
    return calculate_total(data) / len(data)

這邊可以看到我們把功能拆開來,變成更容易讀取

4.2去除重複代碼
目的:消除程式中多次出現的相同或相似的代碼片段,將其抽取為一個單獨的函式。
重點:透過抽象相同邏輯,避免重複編寫,減少未來修改的工作量。
優點:提高代碼的重用性,減少潛在錯誤。

# Before refactoring
def add_user(user):
    # logic for adding user

def remove_user(user):
    # logic for removing user

# After refactoring
def modify_user(user, action):
    if action == 'add':
        # logic for adding user
    elif action == 'remove':
        # logic for removing user

如果你function操作~可以把重複的功能包裝起來

5.返回值(return)

5.1. 定義 (Definition):
return 是 Python 中用來結束函數並返回結果值的語句。當函數執行到 return 語句時,會立即停止函數的運行,並將 return 後面的表達式結果作為函數的輸出返回給呼叫者。如果沒有指定返回值,函數將默認返回 None。

5.2使用時機 (Use Cases)

  • 返回結果給呼叫者:在函數中執行了計算或邏輯處理後,將結果傳回給函數的調用者。
  • 函數的輸出:需要通過函數產生某些值或數據,例如數學計算、數據處理、數據查詢等場景。
  • 流程控制:可以用來根據邏輯條件,提前結束函數並返回結果。

比如說前面學的流程控制
搭配function return的用法

# 判斷並返回年齡級別
def age_category(age):
    if age < 18:
        return "Minor"
    elif age < 65:
        return "Adult"
    else:
        return "Senior"

category = age_category(30)
print(category)  # 輸出 Adult

優點 (Advantages) 缺點 (Disadvantages)
靈活性:允許返回單一或多個值,滿足多種需求。 邏輯複雜化:多次 return 會使邏輯混亂。
增強可重用性:讓函數結果可重複使用。 無法處理異步數據return 不適用於異步處理。
明確結束點:清晰定義函數執行的終點。 潛在錯誤點:可能返回錯誤的數據類型或值。
提高代碼可讀性:清楚展示函數用途與結果。

總結

我們今天把進階程式的最上層function處理完了
希望大家今天收穫滿滿~


上一篇
[Day8] 第二周 - 脫離新手,朝向工程師之路的開端
下一篇
[Day10] 第二週 - 進階工程師的開端 - 模組化程式設計(Modular programming)
系列文
從概念到應用:Python實戰開發學習之旅31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言