回複內容:
這個問題,最近在 cpyug 上面討論得很火熱。我簡要概括一下。
為了考慮為什麼 python 不提供函數重載,首先我們要研究為什麼需要提供函數重載。
函數重載主要是為瞭解決兩個問題。
1。可變參數類型。
2。可變參數個數。
另外,一個基本的設計原則是,僅僅當兩個函數除了參數類型和參數個數不同以外,其功能是完全相同的,此時才使用函數重載,如果兩個函數的功能其實不同,那麼不應當使用重載,而應當使用一個名字不同的函數。
好吧,那麼對於情況 1 ,函數功能相同,但是參數類型不同,python 如何處理?答案是根本不需要處理,因為 python 可以接受任何類型的參數,如果函數的功能相同,那麼不同的參數類型在 python 中很可能是相同的代碼,沒有必要做成兩個不同函數。
那麼對於情況 2 ,函數功能相同,但參數個數不同,python 如何處理?大家知道,答案就是預設參數。對那些缺少的參數設定為預設參數即可解決問題。因為你假設函數功能相同,那麼那些缺少的參數終歸是需要用的。
好了,鑒於情況 1 跟 情況 2 都有瞭解決方案,python 自然就不需要函數重載了。我補充一點,Python3是可以通過metaclass + parameter annotation使某個類
假裝支援function overloading:
class Spam(metaclass=MultipleMeta): def bar(self, x:int, y:int): print('Bar 1:', x, y) def bar(self, s:str, n:int = 0): print('Bar 2:', s, n)# Example: overloaded __init__import timeclass Date(metaclass=MultipleMeta): def __init__(self, year:int, month:int, day:int): self.year = year self.month = month self.day = day def __init__(self): t = time.localtime() self.__init__(t.tm_year, t.tm_mon, t.tm_mday)
誰說不支援了?自己實現個簡易的 multiple dispatch 不就完了。Guido 七年前就給了範例了 [1]。同學們要多讀書,不要隨便被問題挖的坑給埋了……
靜態語言需要 function overloading 主要是為瞭解決調用靈活性的問題,Python 這麼靈活的指令碼語言用 function overloading 純屬多此一舉。
[1]: http://www.artima.com/weblogs/viewpost.jsp?thread=101605
還有別的語言支援這麼變態的特性嗎?請問:
cos(float) cos(double) 和 cosf(float) cosd(double) 兩者相比,前者的易用性在哪?能讓代碼更簡潔?Python支援選擇性參數,比如
def func( a, b = 0, c = 0 ):
pass
那麼,形如func(1),func(1,2),func(1,2,3)或者func(a=1, b=2)這樣的調用都是合法的,這種情況下函數重載就顯得雞肋了。
個人以為,一個語言選擇重載或者選擇性參數兩者中的一種就是了。像C# 4這樣同時支援這兩種形式的,就比較容易混淆。phython是dynamic binding, 就是說已經可以隨便重載,不需要專門定義重載你錯了, 重載overload不是多態的overwrite。 重載是指用相同的函數名,但是參數列表不同(類型和個數), 是不需要虛函數也不需要額外開銷的,是在編譯期由編譯器重新命名函數。如 int f(int) , int f(float); 編譯其可能函數名變為int f_i_1(int) 和 int f_f_1(float). 指令碼語言不需要重載機制是入參本身的類型就不是確定的,既然類型可以是任意 也就帶不來效能上的提高, 就無意義了。 比如python的 sub f(a): , 任意的類型都可以用來刁用fdef max(**kwargs) 可用。因為python是動態語言為啥不行?
def max(a,b,c='nothing'):
if c=='nothing':
if a > b:
print a
else:
print b
else:
......
這比重載更複雜嗎?