# Python 函數
> 原文: [https://javabeginnerstutorial.com/python-tutorial/python-function/](https://javabeginnerstutorial.com/python-tutorial/python-function/)
現在,我們學習了 Python 編程的基礎知識:變量,集合和循環。 如果您按照示例和教程進行操作,您可能會覺得有時我們會使用過多的代碼,因此可以利用它。 但是也許您不知道該怎么做。
大多數時候,解決方案是引入函數。 我們遇到了其他模塊的函數,就像字符串的`isupper()`或`random`模塊的`choice()`一樣。
如果您學習過數學,那么您已經知道函數。 數學家可以與他們一起做非常討厭的事情,但是程序員也可以。 函數的目的是產生僅由傳遞給函數的參數確定的結果。
在編程語言中,我們可以將函數視為黑盒,在其中我們發送定義數量的參數(0 和更多),然后該函數返回結果。 在 Python 中,即使您沒有顯式編寫或查看`return`語句,函數始終會返回結果。 這意味著,如果您知道另一種編程語言(例如 C++ 或 Java),那么您將了解`void`函數。 在 Python 中沒有這種類型-但是,當我告訴您返回值時,我們將在本文后面看到。
## 定義函數
使用`def`語句創建一個函數。 通用語法如下所示:
```py
def function_name(param_list):
function_body statements
```
參數列表包含零個或多個元素。 如果您調用函數,那么您說的是參數而不是參數,但這是術語,在我看來,即使您調用函數也只說參數也是可以的。 如果您不將其聲明為可選參數,則這些參數是必需的。 我們將在下一節中查看可選參數。
每次調用函數時,都會執行其主體中的語句。 當然,您可以使用函數體內的`pass`語句不執行任何操作-但在這種情況下,`pass`語句也將執行。
如您所知:函數必須在其主體中至少包含一個語句。 沒有它,您會得到一個錯誤:
```py
>>> def no_body_function():
...
File "<stdin>", line 2
```
```py
^
IndentationError: expected an indented block
```
嗯,這個錯誤消息并不是最能說明問題的,但是在這種情況下,編譯器缺少縮進的塊-至少有一個針對函數體的語句。
因此,我們編寫一個簡單的函數,它是交換計算器。 它獲得兩個參數:值和匯率,并返回更改后的值(值乘以匯率)。
```py
def exchange(value, rate):
return value*rate
```
因此,每次定義函數時,請確保您具有縮進的主體。 如果您在 Python 的交互式解釋器中遵循本文,則定義將如下所示:
```py
>>> def exchange(value, rate):
...???? return value*rate
...
```
正如我之前提到的,您也可以使用沒有`return`語句的函數。 但是,大多數情況下,您不會使用這些函數,但是為了簡潔起見,我們在這里也看一個示例:
```py
>>> def no_return():
...???? print("This function has no return statement")
...
```
## 調用函數
我認為這很容易。 您已經知道如何調用函數,但讓我們快速進行介紹。 如果您有一個函數定義,則可以通過傳遞正確的參數作為參數來調用它,這很不錯。
正如我之前告訴您的,我們已經調用了函數。 我們首先調用的基本函數是`print()`。 您可以不帶任何參數地調用它,在這種情況下,它將在輸出中輸出換行符(空行)。 另外,我們可以傳遞任意數量的參數,每個參數之間用逗號(`,`)分隔,它們也將被打印到輸出中。
現在,我們調用上一節中定義的兩個函數。
```py
>>> no_return()
This function has no return statement
>>> exchange(123, 1.12)
137.76000000000002
```
如您所見,調用函數沒有什么復雜的。
## 返回值
之前我曾說過,函數會返回值-即使您未顯式編寫`return`語句。 現在是時候驗證我的語句了,因此我將向您展示即使`no_return()`函數也返回一個值,并且該值為`None`。
要查看函數的`return`語句,我們只需將函數調用包裝到`print()`函數調用中即可。
```py
>>> print(no_return())
This function has no return statement
None
>>> print(exchange(123,1.12))
137.76000000000002
```
在這里您可以看到,即使沒有`return`語句的函數也返回`None`。 這意味著在這種情況下,您必須小心使用返回值,因為使用`None`時,僅在布爾表達式中使用它就幾乎無能為力-當然要小心。
```py
>>> result_value = no_return()
This function has no return statement
>>> result_value + 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
```
```py
>>> if result_value == False:
...???? print("Nothing useful...")
... else:
...???? print("Wow, we have got True back!")
...
Wow, we have got True back!
```
如您在上面的示例中看到的,例如,您不能在數學運算中使用`None`,并且`None`不為`False`。
要修復示例的第二部分,我們可以像這樣更改代碼:
```py
>>> if not result_value:
...???? print("Nothing useful...")
... else:
...???? print("Wow, we have got True back!")
...
Nothing useful...
```
只使用沒有任何值的`return`也是如此。 返回結果與沒有返回語句的結果相同。 為什么要這么好? 例如,如果條件求值為`true`,并且您想不返回任何內容,則希望終止函數。 自然地,您可以使用`return None`,但是更多的 pythonic 解決方案將是簡單地使用`return`。
## 可選參數
您可以使用可選參數創建函數。 這意味著不必將這些參數傳遞給函數。 在這種情況下,將使用其默認值-如果可選參數獲得其默認值,有時會跳過語句塊。
可選參數必須遵循強制性參數,并且必須具有默認值。 當您調用函數并且不提供此參數時,將使用此值。
以前面介紹的交換函數為例。 快速提醒一下,這里是定義:
```py
def exchange(value, rate):
return value * rate
```
如果我們嘗試僅使用 1 個參數(帶有值)來調用此交換函數,則會從解釋器中收到錯誤消息:
```py
>>> exchange(42)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: exchange() missing 1 required positional argument: 'rate'
```
現在,將`rate`變量設為可選,并將其默認值設置為 1,以便能夠以相同的貨幣調用此函數而無需進行任何兌換。
因此,解決方案是為函數中的`rate`參數設置默認值,并將該值設置為 1。
要查看其工作原理,我還對代碼進行了一些更改以顯示當前匯率:
```py
>>> def exchange(value, rate=1):
...???? print('Current exchange rate is', rate)
...???? return value * rate
```
現在`rate`參數是可選的,我們可以調用帶有或不帶有`rate`的函數:
```py
>>> exchange(124,0.78)
Current exchange rate is 0.78
96.72
>>> exchange(325,1)
Current exchange rate is 1
325
>>> exchange(42)
Current exchange rate is 1
42
```
可選參數和必需參數的順序很重要。 例如,如果我們更改順序并將`rate = 1`作為`value`之前的第一個參數添加,我們將得到一個錯誤:
```py
>>> def exchange(rate=1, value):
...???? return value * rate
...
File "<stdin>", line 1
SyntaxError: non-default argument follows default argument
```
如果您考慮一下,您將了解為什么會這樣:如果我們提供一個論點,該怎么辦。 是可選的還是必需的? 好吧,口譯員無法分辨,也許您最終會得到錯誤的結果。
## 關鍵字參數
在學習 Python 時,您可能會遇到術語“關鍵字參數”。 實際上,它們與可選參數相同:它們具有名稱和默認值。 這個名稱是關鍵字,您可以使用它為該參數分配一個新值。
讓我們再次看一下前面的示例:`rate`是函數的關鍵字參數。 由于`exchange`只有一個可選參數,因此您可以同時使用兩種參數來調用它:
```py
>>> exchange(42, 1.25)
52.5
>>> exchange(42, rate=1.25)
52.5
```
第二種情況是我們使用關鍵字參數。
現在再來看一個示例,其中有多個可選參數,以便您了解它如何與關鍵字參數一起實際使用。
該示例將非常基礎:我們定義一個函數,該函數采用四個參數`a`,`b`,`c`,`d`并執行以下計算:`a + b – c + d`。 要使其工作,它僅需要 2 個參數,兩個是可選的。
```py
>>> def sub_sum(a, b, c=0, d=0):
...?? return a + b - c + d
...
>>> sub_sum(12,33)
45
```
現在,我們可以選擇傳遞變量`c`和`d`的值。 如果我們已經知道為`c`提供值有兩種選擇。
```py
>>> sub_sum(12,33,0,10)
55
>>> sub_sum(12,33,d=10)
55
```
如您所見,不必提供所有值,在調用函數時為`d`分配值就足夠了。 這就是為什么它們被稱為“關鍵字參數”的原因。 您可能會想到:有些函數帶有很多參數,大多數時候只需要它們的默認值即可。 因此,您無需傳遞它們(因此您不必知道默認值是什么),并且可以使用關鍵字的列表中某個位置的單個參數對函數調用進行微調。
進一步講這個概念,我們可以用一種關鍵字語法調用函數,其方式是您在其他語言中無法想象的:您可以隨意對值進行排序,直到為所有必需的參數提供它們的名稱。
```py
>>> sub_sum(b=12,a=33,d=10)
55
>>> sub_sum(d=10, 8, 11)
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
```
如您所見,如果您弄亂了順序,則不能省略必需參數的名稱。 在這種情況下,需要命名它們,以使解釋器知道您想要設置這些值。
### 關鍵字參數的陷阱
上面我們已經看到了一種使用關鍵字參數的方法。 但是,每個硬幣都有兩個面。 分配這些默認值后,讓我們再深入一點。 它是在創建函數時完成的(因此,在解釋器解析函數定義時),而不是在調用函數時完成。 這意味著只要將不可變類型用于命名參數/關鍵字參數,我們就看不到任何區別。
但是,當我們使用可變變量(例如列表)時,可能會出現問題:
```py
>>> def append_if_short(s, lst=[]):
...???? if len(s) < 4:
...???????? lst.append(s)
...???? return lst
...
```
在上面的示例中,如果`s`的長度最大為 3,則將參數`s`附加到參數`lst`上。如果將兩個參數都傳遞給函數,這似乎很好。 但是讓我們有時調用此函數...
```py
>>> append_if_short("one")
['one']
>>> append_if_short("two")
['one', 'two']
>>> append_if_short("three")
['one', 'two']
>>> append_if_short("four")
['one', 'two']
>>> append_if_short("five")
['one', 'two']
>>> append_if_short("six")
['one', 'two', 'six']
```
如您所見,這會導致意外的行為。 我們傳入一個字符串,并返回一個包含比預期更多的元素的列表。
但是,這還不是全部。 我們會讓事情變得更糟:
```py
>>> def append_if_short(s, lst=[]):
...???? if len(s) < 4:
...???????? lst.append(s)
...???? return lst
...
>>> result = append_if_short("one")
>>> result
['one']
>>> result.append('five')
>>> append_if_short('two')
['one', 'five', 'two']
```
在上面的示例中,我們向列表中添加了一個元素,該元素顯然超過了 3 個字符-這又可能導致意外行為。
要解決此問題,請更改函數定義:
```py
>>> def append_if_short(s, lst=None):
...???? if lst is None:
...???????? lst = []
...???? if len(s) < 4:
...???????? lst.append(s)
...???? return lst
...
>>> result = append_if_short("one")
>>> result
['one']
>>> result.append('five')
>>> append_if_short('two')
['two']
```
## 文檔字符串
有時(我希望每次)您都會有記錄函數的沖動。 您可以使用圍繞函數定義的簡單注釋來完成此操作。
但是,您應該遵循一種常見的做法:*文檔字符串*。 這些是簡單的文檔字符串,位于函數定義之后。 它們具有特殊的三引號格式,因為它們是描述您的函數的多行字符串。
有時文檔比函數本身更長。 約定是使文檔字符串的第一行成為簡短的單行描述,然后在空白行后加上完整的描述,然后給出一些示例(如在交互式解釋器中鍵入的內容)。
因此,讓我們使用此指南并將文檔添加到我們的`append_if_short`函數中。
```py
def append_if_short(s, lst=None):
""" Returns a list containing s if the length of s is smaller than 4.
```
`s`是任何字符串,`lst`是可選的列表類型參數。 如果未提供`lst`,則新的`l??st`將分配一個新的空列表。 如果`len < 4`,則將`s`附加到`lst`并返回`lst`。
```py
>>> append_if_short('one')
['one']
>>> append_if_short('two', ['one'])
['one', 'two']
>>> append_if_short('three', [])
[]
>>> append_if_short('four')
[]
"""
if lst is None:
lst = []
if len(s) < 4:
lst.append(s)
return lst
```
- JavaBeginnersTutorial 中文系列教程
- Java 教程
- Java 教程 – 入門
- Java 的歷史
- Java 基礎知識:Java 入門
- jdk vs jre vs jvm
- public static void main(string args[])說明
- 面向初學者的 Java 類和對象教程
- Java 構造器
- 使用 Eclipse 編寫 Hello World 程序
- 執行順序
- Java 中的訪問修飾符
- Java 中的非訪問修飾符
- Java 中的數據類型
- Java 中的算術運算符
- Java 語句初學者教程
- 用 Java 創建對象的不同方法
- 內部類
- 字符串構建器
- Java 字符串教程
- Java 教程 – 變量
- Java 中的變量
- Java 中的局部變量
- Java 中的實例變量
- Java 引用變量
- 變量遮蓋
- Java 教程 – 循環
- Java for循環
- Java 教程 – 異常
- Java 異常教程
- 異常處理 – try-with-resources語句
- Java 異常處理 – try catch塊
- Java 教程 – OOPS 概念
- Java 重載
- Java 方法覆蓋
- Java 接口
- 繼承
- Java 教程 – 關鍵字
- Java 中的this關鍵字
- Java static關鍵字
- Java 教程 – 集合
- Java 數組教程
- Java 集合
- Java 集合迭代器
- Java Hashmap教程
- 鏈表
- Java 初學者List集合教程
- Java 初學者的Map集合教程
- Java 初學者的Set教程
- Java 初學者的SortedSet集合教程
- Java 初學者SortedMap集合教程
- Java 教程 – 序列化
- Java 序列化概念和示例
- Java 序列化概念和示例第二部分
- Java 瞬態與靜態變量
- serialVersionUID的用途是什么
- Java 教程 – 枚舉
- Java 枚舉(enum)
- Java 枚舉示例
- 核心 Java 教程 – 線程
- Java 線程教程
- Java 8 功能
- Java Lambda:初學者指南
- Lambda 表達式簡介
- Java 8 Lambda 列表foreach
- Java 8 Lambda 映射foreach
- Java 9
- Java 9 功能
- Java 10
- Java 10 獨特功能
- 核心 Java 教程 – 高級主題
- Java 虛擬機基礎
- Java 類加載器
- Java 開發人員必須知道..
- Selenium 教程
- 1 什么是 Selenium?
- 2 為什么要進行自動化測試?
- 3 Selenium 的歷史
- 4 Selenium 工具套件
- 5 Selenium 工具支持的瀏覽器和平臺
- 6 Selenium 工具:爭霸
- 7A Selenium IDE – 簡介,優點和局限性
- 7B Selenium IDE – Selenium IDE 和 Firebug 安裝
- 7C Selenium IDE – 突破表面:初探
- 7D Selenium IDE – 了解您的 IDE 功能
- 7E Selenium IDE – 了解您的 IDE 功能(續)。
- 7F Selenium IDE – 命令,目標和值
- 7G Selenium IDE – 記錄和運行測試用例
- 7H Selenium IDE – Selenium 命令一覽
- 7I Selenium IDE – 設置超時,斷點,起點
- 7J Selenium IDE – 調試
- 7K Selenium IDE – 定位元素(按 ID,名稱,鏈接文本)
- 7L Selenium IDE – 定位元素(續)
- 7M Selenium IDE – 斷言和驗證
- 7N Selenium IDE – 利用 Firebug 的優勢
- 7O Selenium IDE – 以所需的語言導出測試用例
- 7P Selenium IDE – 其他功能
- 7Q Selenium IDE – 快速瀏覽插件
- 7Q Selenium IDE – 暫停和反射
- 8 給新手的驚喜
- 9A WebDriver – 架構及其工作方式
- 9B WebDriver – 在 Eclipse 中設置
- 9C WebDriver – 啟動 Firefox 的第一個測試腳本
- 9D WebDriver – 執行測試
- 9E WebDriver – 用于啟動其他瀏覽器的代碼示例
- 9F WebDriver – JUnit 環境設置
- 9G WebDriver – 在 JUnit4 中運行 WebDriver 測試
- 9H WebDriver – 隱式等待
- 9I WebDriver – 顯式等待
- 9J WebDriver – 定位元素:第 1 部分(按 ID,名稱,標簽名稱)
- 9K WebDriver – 定位元素:第 2 部分(按className,linkText,partialLinkText)
- 9L WebDriver – 定位元素:第 3a 部分(按cssSelector定位)
- 9M WebDriver – 定位元素:第 3b 部分(cssSelector續)
- 9N WebDriver – 定位元素:第 4a 部分(通過 xpath)
- 9O WebDriver – 定位元素:第 4b 部分(XPath 續)
- 9P WebDriver – 節省時間的捷徑:定位器驗證
- 9Q WebDriver – 處理驗證碼
- 9R WebDriver – 斷言和驗證
- 9S WebDriver – 處理文本框和圖像
- 9T WebDriver – 處理單選按鈕和復選框
- 9U WebDriver – 通過兩種方式選擇項目(下拉菜單和多項選擇)
- 9V WebDriver – 以兩種方式處理表
- 9W WebDriver – 遍歷表元素
- 9X WebDriver – 處理警報/彈出框
- 9Y WebDriver – 處理多個窗口
- 9Z WebDriver – 最大化窗口
- 9AA WebDriver – 執行 JavaScript 代碼
- 9AB WebDriver – 使用動作類
- 9AC WebDriver – 無法輕松定位元素? 繼續閱讀...
- 10A 高級 WebDriver – 使用 Apache ANT
- 10B 高級 WebDriver – 生成 JUnit 報告
- 10C 高級 WebDriver – JUnit 報表自定義
- 10D 高級 WebDriver – JUnit 報告自定義續
- 10E 高級 WebDriver – 生成 PDF 報告
- 10F 高級 WebDriver – 截屏
- 10G 高級 WebDriver – 將屏幕截圖保存到 Word 文檔
- 10H 高級 WebDriver – 發送帶有附件的電子郵件
- 10I 高級 WebDriver – 使用屬性文件
- 10J 高級 WebDriver – 使用 POI 從 excel 讀取數據
- 10K 高級 WebDriver – 使用 Log4j 第 1 部分
- 10L 高級 WebDriver – 使用 Log4j 第 2 部分
- 10M 高級 WebDriver – 以無頭模式運行測試
- Vue 教程
- 1 使用 Vue.js 的 Hello World
- 2 模板語法和反應式的初探
- 3 Vue 指令簡介
- 4 Vue Devtools 設置
- 5 數據綁定第 1 部分(文本,原始 HTML,JavaScript 表達式)
- 6 數據綁定第 2 部分(屬性)
- 7 條件渲染第 1 部分(v-if,v-else,v-else-if)
- 8 條件渲染第 2 部分(v-if和v-show)
- 9 渲染列表第 1 部分(遍歷數組)
- 10 渲染列表第 2 部分(遍歷對象)
- 11 監聽 DOM 事件和事件修飾符
- 12 監聽鍵盤和鼠標事件
- 13 讓我們使用簡寫
- 14 使用v-model進行雙向數據綁定
- 15 表單輸入綁定
- 18 類綁定
- Python 教程
- Python 3 簡介
- Python 基礎知識 - 又稱 Hello World 以及如何實現
- 如何在 Windows 中安裝 python
- 適用于 Windows,Mac,Linux 的 Python 設置
- Python 數字和字符串
- Python 列表
- Python 集
- Python 字典
- Python 條件語句
- Python 循環
- Python 函數
- 面向對象編程(OOP)
- Python 中的面向對象編程
- Python 3 中的異常處理
- Python 3:猜數字
- Python 3:猜數字 – 回顧
- Python 生成器
- Hibernate 教程
- Hibernate 框架基礎
- Hibernate 4 入門教程
- Hibernate 4 注解配置
- Hibernate 4 的實體關系
- Hibernate 4 中的實體繼承模型
- Hibernate 4 查詢語言
- Hibernate 4 數據庫配置
- Hibernate 4 批處理
- Hibernate 4 緩存
- Hibernate 4 審計
- Hibernate 4 的并發控制
- Hibernate 4 的多租戶
- Hibernate 4 連接池
- Hibernate 自舉