Python:函數基礎

来源:https://www.cnblogs.com/Rohn/archive/2020/07/20/13347859.html
-Advertisement-
Play Games

函數的本質就是**一段有特定功能、可以重覆使用的代碼**,這段代碼已經被提前編寫好了,並且為其起一個好聽的名字。在後續編寫程式過程中,如果需要同樣的功能,直接通過起好的名字就可以調用這段代碼。 ...


Blog:https://www.cnblogs.com/Rohn

目錄

函數基礎

除了可以直接使用的內置函數外,Python還支持自定義函數,即將一段有規律的、可重覆使用的代碼定義成函數,從而達到一次編寫、多次調用的目的。

函數的本質就是一段有特定功能、可以重覆使用的代碼,這段代碼已經被提前編寫好了,並且為其起一個好聽的名字。在後續編寫程式過程中,如果需要同樣的功能,直接通過起好的名字就可以調用這段代碼。

函數的作用

  • 結構化編程對代碼的最基本的封裝,一般按照功能組織一段代碼;
  • 封裝的目的為了復用,減少冗餘代碼;
  • 代碼更加簡潔美觀、可讀易懂

函數的定義

Python函數:能完成一定的功能,由若幹語句組成的語句塊、函數名稱、參數列表構成,它是組織代碼的最小單元。

語法格式

def 函數名(參數1,參數2,參數3,...):
    '''註釋'''
    函數體
    return 返回的值

需要註意的地方:

  • 函數名後面必須加冒號;
  • 函數名即標識符,命名規範:小寫字母,多個單詞用_間隔;
  • 如果函數體和def不在同一行,必須縮進,約定4個空格;
  • 若沒有return,則隱式返回一個None值;
  • 如果函數體body語句只有一行,或者可以簡寫為一行,則可以寫在def的同行。例如:
def myfunc(x,y,z): print(x+y+z)

函數的調用

如何調用

函數聲明好之後,就可以執行函數,執行函數也稱為調用函數,方式為func_name(args),例如:

myfunc(1,2,3)

調用規則

函數的使用,必須遵循原則:先定義,後調用

若在前面調用了,後面再定義,是否會報錯呢?

測試一:

def bar():
    print('from bar')

def foo():
    print('from foo')
    bar()
foo() # 正常

測試二:

def foo():
    print('from foo')
    bar()
    
def bar():
    print('from bar')
foo() # 也正常

測試三:

def foo():
    print('from foo')
    bar()

foo()    
    
def bar():
    print('from bar')
# 報錯
NameError: name 'bar' is not defined

函數的返回值

函數返回值:

  • 沒有返回值:預設返回None
  • 返回一個值:函數結束了且返回一個值
  • 返回多個值:多個值之間用逗號隔開,接收的時候可以用一個變數接收(返回元組),也可以用等量的多個變數接收

什麼時候需要有返回值?

調用函數,經過一系列的操作,最後要拿到一個明確的結果,則必須要有返回值。

通常有參函數需要有返回值,輸入參數,經過計算,得到一個最終的結果。

什麼時候不需要有返回值?

調用函數,僅僅只是執行一系列的操作,最後不需要得到什麼結果,則無需有返回值。

通常無參函數不需要有返回值。

多個返回值

Python的函數支持返回多個值。返回多個值時,預設以tuple的方式返回。例如,下麵兩個函數的定義是完全等價的。

def f():
    return 1,2

def f():
    return (1,2)

丟棄返回值

# 不進行任何賦值,將丟棄所有返回值
f()

# 可以通過索引取得某個或某幾個返回值
a = f()[0]
b = f()[1]

# 使用雙下劃線__或更多下劃線___________
# 丟棄第二個返回值
a, __ = f()

函數調用時的***

除了在def定義函數時,參數中可以使用***收集參數,在函數調用的時候也可以使用***分別解包元組(列表或其它對象)、字典。一定要註意區分函數定義和函數調用時的***,它們的用法是不通用的。

例如,解包元組:

def f(a,b,c,d):
    print(a)
    print(b)
    print(c)
    print(d)

T=(1,2,3,4)
f(*T)

*除了可以解包元組,還可以解包其它可迭代對象,例如列表。甚至是字典也能解包,只不過*解包的字典得到的是key組成的參數列表,和value無關:

D=dict(a=11,b=22,c=33,d=44)
f(*D)

# 輸出:
a
b
c
d

**解包的字典則是key=value組成的參數列表。以下是函數調用時使用**進行解包,字典D中的key名稱必須和def中定義的參數名稱相同:

def f(a,b,c,d):
    print(a)
    print(b)
    print(c)
    print(d)

D=dict(a=11,b=22,c=33,d=44)
f(**D)

# 輸出:
11
22
33
44

在函數調用時,可以混合位置參數、關鍵字參數、*解包參數、**解包參數。用法非常的靈活:

def f(a,b,c,d):
    print(a)
    print(b)
    print(c)
    print(d)

f(*(1,2),**{'d':4,'c':3})

f(1,*(2,3),**{'d':4})

f(1,c=3,*(2,),**{'d':4})

f(1,*(2,3),d=4)

f(1,*(2,),c=3,**{'d':4})

# 結果如下
1
2
3
4
1
2
3
4
1
2
3
4
1
2
3
4
1
2
3
4

上面調用函數時的效果都等同於f(1,2,3,4)

函數的參數

函數的參數其實也是變數,只不過這些變數是獨屬於函數的本地變數,函數外部無法訪問。在函數調用的時候,會將給定的值傳遞給函數的參數,這實際上是變數賦值的過程。例如:

def myfunc(x,y,z):
    print(x,y,z)

myfunc(1,2,3)

形參和實參

形參即變數名,實參即變數值,函數調用時,將值綁定到變數名上,函數調用結束,解除綁定。

形參:定義函數時,小括弧中的參數,是用來接收參數用的,在函數內部作為變數使用。

實參:調用函數時,小括弧中的參數,是用來把數據傳遞到函數內部用的。

參數的傳遞

參數的傳遞可以分為按指針傳參、按位置傳參、按關鍵字key=value方式傳參。

按指針傳參

Python中變數賦值、參數傳遞都是通過指針拷貝的方式進行的。都只是拷貝了源數據的一個地址,而不會拷貝記憶體中完整的數據對象副本。所以,如果在函數內部修改變數指向的數據對象,會影響函數外部的數據。

例如:

def f(x):
    print(x+3)


a = 4
f(a)

# 輸出結果
7

按位置傳參

如果是多個參數,則按從左到右的順序進行參數變數的賦值:

def f(x, y, z):
    print(x)
    print(y)
    print(z)


f(2, 3, 4)

# 輸出結果
2
3
4

調用f(2,3,4)的時候,會按照從左向右的位置方式對本地變數x、y、z賦值:x=2,y=3,z=4

按關鍵字key=value方式傳參

Python還支持key=value的方式設置函數調用時的參數,使用key=value的方式賦值時,順序不重要。這種函數調用時的傳值方式稱為關鍵字傳值

例如:

def f(x, y, z):
    print(x)
    print(y)
    print(z)


f(x=3, y="haha", z=4)

# 輸出
3
haha
4

也可以打亂順序,輸出結果不變:

f(x=3, z=4, y="haha")

還可以將key=value和位置傳參的方式進行混合:

f(3, "haha", z=4)

但混合按位置傳參方式的時候,位置參數必須在其它傳參方式的前面,不僅此處結合key=value時如此,後文中位置參數結合其它方式傳參也都如此:位置參數必須在最前面。例如,下麵的傳參方式是錯的:

f(z=4, 3, "haha")

參數預設值

在def或lambda聲明函數的時候,可以通過var=default的方式指定參數的預設值。

例如:

def f(x=3):
    print(x)


f(4)
f("haha")
f()

# 輸出結果
4
haha
3

上面的f(4)f("haha")都對函數f()的本地變數x進行了賦值。但是最後一個調用語句f()未賦值,而是使用參數的預設值3

設置參數預設值時,如果函數有多個參數,則帶預設值參數後面必須放在最後面。例如:

# 正確
def f(x, y, z=4)
def f(x, y=1, z=4)

# 錯誤
def f(x, y=4, z)

只要為參數設置了預設值,那麼調用函數的時候,這個參數就是可選的,可有可無的,如果沒有,則採用預設值。

def f(x, y=2, z=4):
    print(x)
    print(y)
    print(z)


# 不採用任何預設值
f(2, 3, 4)

# 採用z的預設值
f(2, 3)

# 採用y的預設值
# 此時z必須按key=value的方式傳值
f(2, z=5)

# y、z都採用預設值
f(2)

# 輸出結果
2
3
4
2
3
4
2
2
5
2
2
4

位置可變參數*

對於任意長度的參數,可以在def聲明的函數中使用*將各位置參數收集到一個元組中。

def f(*args):
    print(args)


f(1, 2, 3, 4)

# 結果輸出:(1, 2, 3, 4)

上面調用f(1, 2, 3, 4)的時候,將所有參數都收集到了一個名為args的元組中。

既然是元組,就可以對參數進行迭代遍歷:

def f(*args):
    for arg in args:
        print(arg)

f(1,2,3,4)

# 輸出結果
1
2
3
4

必須註意,*是按位置收集參數的。

def f(x, y, *args):
    print(x)
    print(y)
    for arg in args:
        print(arg)


f(1, 2, 3, 4)

按照從左向右的傳參規則,首先將1賦值給x,將2賦值給y,然後將剩餘所有的位置參數收集到args元組中,所以args=(3,4)

如果*後面還有參數,則調用函數的時候,後面的參數必須使用key=value的方式傳遞,否則會收集到元組中,從而導致參數缺少的問題:

def f(x, *args, y):
    print(x)
    print(y)
    for arg in args:
        print(arg)


# 正確
f(1, 3, 4, y=2)

# 錯誤
f(1, 2, 3, 4)

上面調用f(1, 3, 4, y=2)的時候,會按照位置參數對x賦值為1,然後將所有位置參數收集到元組args中,因為y=2是非位置參數傳值方式,所以args=(3, 4)

如果為上面的y設置預設值:

def f(x, *args, y=2)

那麼f(1, 2, 3, 4)會將(2, 3, 4)都收集到元組args中,然後y採用預設值2

關鍵字可變參數**

除了可以使用*將位置參數收集到元組中,還可以使用**key=value格式的參數收集到字典中。

例如:

def f(x, **args):
    print(x)
    print(args)


f(1, a=11, b=22, c=33, d=44)

既然是將參數收集到字典中,就可以使用字典類的工具操作這個字典。例如,遍歷字典。

**的後面不能出現任何其它類型的參數。例如,下麵的都是錯誤的def定義方式:

def f(x, **args, y)
def f(x, **args, y=3)
def f(x, **args, *t)

只能將位置參數或者*的收集放在**的前面。

def f(x, y, **args)
def f(x, *args1, **args2)

keyword-only參數形式

keyword-only的參數傳值方式表示def中如果使用了*,那麼在調用函數時,它後面的參數必須只能使用關鍵字傳值。其實在前面的內容中已經出現過幾次與之相關的說明。

另外註意,*才是keyword-only開關,**不是,雖然**也有自己的一些語法限制:任意類型的參數定義都必須在**之前,包括keyword-only類型的參數。例如:

def f(a, *b, c):
    print(a, b, c)

按照keyword-only的規則,被*b收集的位置參數不包括c,這個c必須只能使用關鍵字的方式傳值,否則就被當作位置參數被收集到元組b中。

# 正確
f(1, 2, 3, c=4)

# 錯誤
f(1, 2, 3, 4)

# 錯誤
f(1, c=4, 2, 3)

其中最後一個錯誤和如何def的定義無關,而是函數調用時的語法錯誤,前面已經解釋過:位置參數必須放在最前面。

還可以直接使用*而非*args的方式,這表示不收集任何參數,但卻要求它後面的參數必須按照關鍵字傳值的方式。

def f(a, *, b, c):
    print(a, b, c)

以下是正確和錯誤的調用方式示例:

# 正確
f(1, b=2, c=3)
f(1, c=3, b=2)
f(b=2, c=3, a=1)

# 錯誤
f(1, 2, 3)
f(1, 2, c=3)
f(1, b=2, 3)

不過,keyword-only後面的參數可以使用參數預設值。

def f(a, *, b, c=3)

那麼c是可選的,但如果給定,則必須按關鍵字方式傳值。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Django template層之json報文遍歷總結 by:授客 QQ:1033553122 測試環境 Win7 Django 1.11 實例 Views.py def home(request): home_page = 'website/pages/home.html' nav_menus = ...
  • 我今天在某博客平臺上看到了一則留言: 非常意外!不會只是巧合吧? 我馬上就點開鏈接去核實,然後發現那篇文章是全文翻譯了我之前寫的文章,而且該作者還翻譯了另外的兩篇。 如果讀者瞭解我,應該知道我也翻譯過不少文章,比如有 PEP系列 、Guido的解析器系列 、Flask 作者 Armin Ronach ...
  • 本文源碼:GitHub·點這裡 || GitEE·點這裡 一、頁面靜態化 1、動靜態頁面 靜態頁面 即靜態網頁,指已經裝載好內容HTML頁面,無需經過請求伺服器數據和編譯過程,直接載入到客戶瀏覽器上顯示出來。通俗的說就是生成獨立的HTML頁面,且不與伺服器進行數據交互。 優缺點描述: 靜態網頁的內容 ...
  • class ListNode: def __init__(self, x): self.val = x self.next = Noneclass Solution: def swapPairs(self, head: ListNode) -> ListNode: # 定義一個節點,並將它指向頭結點 ...
  • class ListNode: def __init__(self, x): self.val = x self.next = None# 快慢指針的做法,定義兩個指針,一個走一步,一個走兩步# 如果他們不相遇的話,那就是沒有環,如果在某一時刻相遇,# 就說明是有環的。class Solution: ...
  • 隨著人工智慧以及腳本開發火熱,Python已經被推上一個非常火熱的巔峰! 那麼,想要學習Python卻又不知道從哪裡開始的朋友,看這裡呀~ Python在整個編程語言來說,是比較容易上手,而且“見效”特別快的! 下麵我就來推薦一些比較好上手,而且會讓整個學習過程變得更加輕鬆而快速! 基礎學習 進階技 ...
  • # Definition for singly-linked list.class ListNode: def __init__(self, x): self.val = x self.next = Nonea = ListNode(1)b = ListNode(2)a.next = b# 有關鏈表 ...
  • 如果不是領導強制要求,可能根本不會留意到這款號稱世界上功能最強大的開源資料庫——PostgreSQL。如果你不讀這篇文章,或許也會錯過一個躍躍欲試想擠進前三的優秀資料庫。 為了能夠熟練運用,特意買書研究,發現這款資料庫還真有點意思。彙總一篇文章與大家分享,目的只有一個:讓大家多少瞭解一下這款資料庫。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...