缺省參數
在程序設計中,一個函數的缺省參數是指不必須指定值的參數。在大多數程序設計語言中,函數可以接受一個或多個參數。通常對於每個參數都需要指定它們的值(例如C語言[1])。一些較新的程序設計語言(例如C++)允許程序員設定缺省參數並指定默認值,當調用該函數並未指定值時,該缺省參數將為缺省值。
C++中的缺省參數
考慮如下函數聲明:
int my_func(int a, int b, int c=12);
該函數有三個參數,最後一個參數的缺省值為12。程序員可以用以下兩種方式調用該函數:
result = my_func(1, 2, 3);
result = my_func(1, 2);
第一種調用方式中,c的值就像一般函數一樣被設為3。在第二種調用方式中,c被省略,而被直接賦值為缺省值12。
在函數體中,無法知道參數值是在調用時指定的還是直接使用的缺省值。
這種定義方法在希望不論是否指定參數時都可以調用函數的情況下尤其有用,考慮下面的例子:
void printToScreen(istream &input = cin)
{
// this outputs any input to the screen
cout << input;
}
函數調用:
printToScreen();
這個函數調用會默認將鍵盤輸入打印到屏幕輸出。通過這種用法打印到屏幕,比起下面的用法是更為合適的:
printToScreen(cin);
另一方面,任何一種輸入流都可以作為參數傳入該函數。此時該函數會將指定輸入流的內容輸出到屏幕,例如:
printToScreen(fileName);
fileName是通過文件流ifstream打開的可讀文件。
重載方法
在Java等一些其他語言中,不支持缺省參數。但可以用過函數重載(方法重載)的方式來支持不同數量的參數。通過方法重載,讓參數少的方法直接調用參數多的方法並指定缺省值,就可以達到同樣的效果。例如:
int MyFunc(int a, int b) { return MyFunc(a, b, 12); }
int MyFunc(int a, int b, int c) { /* main implementation here */ }
評價
對於每一次使用缺省參數值的函數調用,缺省的函數值都必須要傳遞一次,相比於函數重載,這造成了代碼臃腫。
如果缺省參數不是一個值而是一個表達式,何時計算該表達式則是新的問題。究竟是整個程序運行期間計算一次(語法解釋時、編譯時或運行時)還是每一次調用都計算一次。
Python只在模塊載入時計算一次缺省參數表達式的值。如果我們需要每次調用都計算缺省值,則可以將缺省值設置為監視哨,例如設為None
。隨後在函數第一行,檢查監視哨,如果監視哨是默認值,則計算所需表達式的值。
例如我們可以通過以下方法使函數在每一次使用缺省值時都重新獲取當前的時間:
import datetime
def f(a, b=None):
b = b or datetime.datetime.now()
作用域和生存周期
一般而言,缺省參數就像一個傳入的函數參數或一個在函數開頭定義的局部變量一樣,擁有和局部變量一致的作用域和生存周期。作為一個自動變量會在函數終止時被釋放。
在另外一些情況下,缺省參數會被靜態分配。就像靜態變量,如果缺省參數的值發生了改變,則在所有函數調用中都會發生相應改變。
這種情況在Python中存在。如果缺省參數是可變類型(例如列表),則該缺省參數就會被靜態分配。為保證缺省參數為局部變量,可以使用監視哨之方法實現,就例如:
def f(a, b=None):
b = b or []