
詳細介紹Python函數(shù)中的默認參數(shù)
最近我在一段Python代碼中發(fā)現(xiàn)了一個因為錯誤的使用默認參數(shù)而產生的非常惡心的bug。如果您已經知道關于默認參數(shù)的全部內容了,只是想嘲笑一下我這可笑的錯誤,請直接跳到本文末尾。哎,這段代碼是我寫的,但是我非常確定那天我被惡魔附體了。你懂的,有時候就是這樣。
本文僅僅是總結一下關于Python函數(shù)的標準參數(shù)和默認參數(shù)的一些基本內容。提醒你注意你的代碼中可能存在的陷阱。如果你剛開始接觸Python,開始寫一些函數(shù),我真心推薦你看一下Python官方手冊中關于函數(shù)的內容,鏈接如下:Defining Functions 以及 More on Defining Functions。
簡單復習一下函數(shù)
Python是一個強大的面向對象語言,它把這種編程范式推向了頂峰。但是,面向對象編程仍然需要依靠函數(shù)這一概念,你可以用它來處理數(shù)據(jù)。Python對于可調用對象有一個更寬泛的概念,即任何對象都可以被調用,調用的意思是對其應用數(shù)據(jù)。
函數(shù)在Python中是可調用對象,并且乍一看,它和其他語言中的函數(shù)有著類似的行為。它們獲取一些數(shù)據(jù),這些數(shù)據(jù)被稱為參數(shù),然后處理它們,接著返回結果(如果沒有return語句則是None)
參數(shù)被聲明為占位符(在定義函數(shù)的時候),用以代表那些當函數(shù)調用時被實際傳入的對象。在Python中你不需要聲明參數(shù)的類型(例如,像你在C或Java中做的那樣)因為Python哲學依賴于多態(tài)。
記住,Python的變量是引用,即實際變量的內存地址。這意味著Python的函數(shù)永遠以“傳址”的方式工作(這里使用了一個C/C++術語),當你調用一個函數(shù)的時候,并不是復制了一份參數(shù)的值來替換占位符,而是把占位符指向了變量本身。這導致了一個非常重要的結果:你可以在函數(shù)內部改變這個變量的值。這里有一個很好可視化講解,關于引用機制。
引用在Python扮演著非常重要的角色,它是Python完全多態(tài)方式的骨干。關于這個非常重要的主題,請點擊這個鏈接 查看更好的解釋。
為了檢查你是否理解了這門語言的這一基本特性,請跟隨這段簡單的代碼(變量ph代表的是“占位符(placeholder)”)
>>> def print_id(ph):
... print(hex(id(ph)))
...
>>> a = 5
>>> print(hex(id(a)))
0x84ab460
>>> print_id(a)
0x84ab460
>>>
>>> def alter_value(ph):
... ph = ph + 1
... return ph
...
>>> b = alter_value(a)
>>> b
6
>>> a
5
>>> hex(id(a))
'0x84ab460'
>>> hex(id(b))
'0x84ab470'
>>>
>>> def alter_value(ph):
... ph.append(1)
... return ph
...
>>> a = [1,2,3]
>>> b = alter_value(a)
>>> a
[1, 2, 3, 1]
>>> b
[1, 2, 3, 1]
>>> hex(id(a))
'0xb701f72c'
>>> hex(id(b))
'0xb701f72c'
>>>
如果你對這里發(fā)生的事情并不感到吃驚,那說明你已經掌握了Python中最為重要的部分之一,你可以放心的跳過下面的解釋了。
print_id()函數(shù)顯示,函數(shù)內部的占位符同運行時傳入的變量完全一樣(它們的內存地址一致)。
兩個版本的alter_value()意在改變傳入參數(shù)的值。正如你所看到的,第一個alter_value() 并沒有像第二個alter_value()一樣成功的改變變量a的值。這是為什么呢?實際上兩者的行為是一樣的,都是嘗試修改傳入的原始變量的值,但是在Python中,有些變量是不可變的(immutable),整數(shù)就在此列。另一方面,列表并不是不可變的,所以函數(shù)得以完成它的名字所保證的工作。 在這里,你可以找到關于不可變類型的更加詳細的介紹 。
關于Python中的函數(shù),還有一些要說的,但是這些是關于標準的參數(shù)的基本知識。
默認參數(shù)值
有時候你需要定義一個函數(shù),讓它接受一個參數(shù),而且在這個參數(shù)出現(xiàn)或不出現(xiàn)時,函數(shù)有不同的行為。如果一門語言不支持這種情況,你就只有兩個選擇:第一種是定義兩個不同的函數(shù),決定每次調用應該選擇調用哪個,第二種是 兩種方法都是可行的,但是都不是最佳的。
Python和其他語言一樣,支持默認參數(shù)值,即函數(shù)參數(shù)可以是調用時指定的,也可以留空,自動接受一個預定義的值。
一個關于默認值的非常簡單(也很沒用)的例子如下:
def log(message=None):
if message:
print("LOG: {0}".format(message))
這個函數(shù)可以帶一個參數(shù)運行(可以是None)
>>> log("File closed")
LOG: File closed
>>> log(None)
>>>
但是同樣也可以不帶參數(shù)運行,這種情況下它會接受一個函數(shù)原型中設置的默認值(本例中是None)
>>> log()
>>>
你可以在標準庫中找到更多有趣的例子,比如在open()函數(shù)中(請查看官方文檔)
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
函數(shù)原型可以證明,例如 f = open('/etc/hosts')這樣的調用,通過傳入默認值隱藏了很多參數(shù) (mode, buffering, encoding, 等),并且使這個函數(shù)的典型應用案例變得非常簡單易用。
正如你在內建的open()函數(shù)中看到的那樣,我們可以在函數(shù)中使用標準或者默認參數(shù),但是兩者在函數(shù)中出現(xiàn)的次序是固定的:首先調用標準參數(shù),然后調用默認參數(shù)。
def a_rich_function(a, b, c, d=None, e=0):
pass
原因是顯而易見的:如果我們可以在標準參數(shù)前面放置一個默認參數(shù),語言就無法理解,默認參數(shù)是否已經被初始化。例如,考慮下面這個函數(shù)定義
def a_rich_function(a, b, d=None, c, e=0):
pass
當調用函數(shù)a_rich_function(1, 2, 4, 5)時,我們傳入了什么參數(shù)? 是d=4, c=5 還是c=4, e=5?因為d有一個默認的值。因此這種順序的定義是被禁止的,如果你這樣做,Python會拋出一個SyntaxError
>>> def a_rich_function(a, b, d=None, c, e=0):
... pass
...
File "<stdin>", line 1
SyntaxError: non-default argument follows default argument
>>>
默認參數(shù)求值
默認參數(shù)可以通過普通值或是函數(shù)調用結果來提高,但是后者這種技術需要一個特別的警示
一個普通的值是硬編碼的,因此除了編譯時,其他時候是不需要求值的,但是函數(shù)調用期望在運行時執(zhí)行求值。所以我們可以這樣寫
import datetime as dt
def log_time(message, time=dt.datetime.now()):
print("{0}: {1}".format(time.isoformat(), message))
每次我們調用log_time()時都期望它能夠正確提供當前時間。悲劇的是并沒有成功:默認參數(shù)在定義時求值(比如說當你首次導入模塊時),調用的結果如下
>>> log_time("message 1")
2015-02-10T21:20:32.998647: message 1
>>> log_time("message 2")
2015-02-10T21:20:32.998647: message 2
>>> log_time("message 3")
2015-02-10T21:20:32.998647: message 3
如果把默認值賦給一個類的實例,結果會更加奇怪,你可以在Hitchhiker's Guide to Python!中讀到相關內容。根據(jù)。。通常的解決方法是把默認參數(shù)替換為None,并且在函數(shù)內部檢查參數(shù)值。
結論
默認參數(shù)能夠極大的簡化API,你需要關注它唯一的“失敗點”,即求值的時機。令人驚奇的是,Python最基本的內容之一,函數(shù)的參數(shù)和引用,是最大的錯誤源之一,有時候對于有經驗的程序員也一樣。我建議抽時間學習一下引用和多態(tài)。
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
LSTM 模型輸入長度選擇技巧:提升序列建模效能的關鍵? 在循環(huán)神經網絡(RNN)家族中,長短期記憶網絡(LSTM)憑借其解決長序列 ...
2025-07-11CDA 數(shù)據(jù)分析師報考條件詳解與準備指南? ? 在數(shù)據(jù)驅動決策的時代浪潮下,CDA 數(shù)據(jù)分析師認證愈發(fā)受到矚目,成為眾多有志投身數(shù) ...
2025-07-11數(shù)據(jù)透視表中兩列相乘合計的實用指南? 在數(shù)據(jù)分析的日常工作中,數(shù)據(jù)透視表憑借其強大的數(shù)據(jù)匯總和分析功能,成為了 Excel 用戶 ...
2025-07-11尊敬的考生: 您好! 我們誠摯通知您,CDA Level I和 Level II考試大綱將于 2025年7月25日 實施重大更新。 此次更新旨在確保認 ...
2025-07-10BI 大數(shù)據(jù)分析師:連接數(shù)據(jù)與業(yè)務的價值轉化者? ? 在大數(shù)據(jù)與商業(yè)智能(Business Intelligence,簡稱 BI)深度融合的時代,BI ...
2025-07-10SQL 在預測分析中的應用:從數(shù)據(jù)查詢到趨勢預判? ? 在數(shù)據(jù)驅動決策的時代,預測分析作為挖掘數(shù)據(jù)潛在價值的核心手段,正被廣泛 ...
2025-07-10數(shù)據(jù)查詢結束后:分析師的收尾工作與價值深化? ? 在數(shù)據(jù)分析的全流程中,“query end”(查詢結束)并非工作的終點,而是將數(shù) ...
2025-07-10CDA 數(shù)據(jù)分析師考試:從報考到取證的全攻略? 在數(shù)字經濟蓬勃發(fā)展的今天,數(shù)據(jù)分析師已成為各行業(yè)爭搶的核心人才,而 CDA(Certi ...
2025-07-09【CDA干貨】單樣本趨勢性檢驗:捕捉數(shù)據(jù)背后的時間軌跡? 在數(shù)據(jù)分析的版圖中,單樣本趨勢性檢驗如同一位耐心的偵探,專注于從單 ...
2025-07-09year_month數(shù)據(jù)類型:時間維度的精準切片? ? 在數(shù)據(jù)的世界里,時間是最不可或缺的維度之一,而year_month數(shù)據(jù)類型就像一把精準 ...
2025-07-09CDA 備考干貨:Python 在數(shù)據(jù)分析中的核心應用與實戰(zhàn)技巧? ? 在 CDA 數(shù)據(jù)分析師認證考試中,Python 作為數(shù)據(jù)處理與分析的核心 ...
2025-07-08SPSS 中的 Mann-Kendall 檢驗:數(shù)據(jù)趨勢與突變分析的有力工具? ? ? 在數(shù)據(jù)分析的廣袤領域中,準確捕捉數(shù)據(jù)的趨勢變化以及識別 ...
2025-07-08備戰(zhàn) CDA 數(shù)據(jù)分析師考試:需要多久?如何規(guī)劃? CDA(Certified Data Analyst)數(shù)據(jù)分析師認證作為國內權威的數(shù)據(jù)分析能力認證 ...
2025-07-08LSTM 輸出不確定的成因、影響與應對策略? 長短期記憶網絡(LSTM)作為循環(huán)神經網絡(RNN)的一種變體,憑借獨特的門控機制,在 ...
2025-07-07統(tǒng)計學方法在市場調研數(shù)據(jù)中的深度應用? 市場調研是企業(yè)洞察市場動態(tài)、了解消費者需求的重要途徑,而統(tǒng)計學方法則是市場調研數(shù) ...
2025-07-07CDA數(shù)據(jù)分析師證書考試全攻略? 在數(shù)字化浪潮席卷全球的當下,數(shù)據(jù)已成為企業(yè)決策、行業(yè)發(fā)展的核心驅動力,數(shù)據(jù)分析師也因此成為 ...
2025-07-07剖析 CDA 數(shù)據(jù)分析師考試題型:解鎖高效備考與答題策略? CDA(Certified Data Analyst)數(shù)據(jù)分析師考試作為衡量數(shù)據(jù)專業(yè)能力的 ...
2025-07-04SQL Server 字符串截取轉日期:解鎖數(shù)據(jù)處理的關鍵技能? 在數(shù)據(jù)處理與分析工作中,數(shù)據(jù)格式的規(guī)范性是保證后續(xù)分析準確性的基礎 ...
2025-07-04CDA 數(shù)據(jù)分析師視角:從數(shù)據(jù)迷霧中探尋商業(yè)真相? 在數(shù)字化浪潮席卷全球的今天,數(shù)據(jù)已成為企業(yè)決策的核心驅動力,CDA(Certifie ...
2025-07-04CDA 數(shù)據(jù)分析師:開啟數(shù)據(jù)職業(yè)發(fā)展新征程? ? 在數(shù)據(jù)成為核心生產要素的今天,數(shù)據(jù)分析師的職業(yè)價值愈發(fā)凸顯。CDA(Certified D ...
2025-07-03