2013-07-13 70 views
8

在Python中,是否可以在運行時重新定義函數的默認參數?是否有可能在Python中更改函數的默認參數?

予定義的函數具有3個參數這裏:

def multiplyNumbers(x,y,z): 
    return x*y*z 

print(multiplyNumbers(x=2,y=3,z=3)) 

接着,我試圖(不成功)來設定y的默認參數值,然後我試圖調用該函數不包含該參數y

multiplyNumbers.y = 2; 
print(multiplyNumbers(x=3, z=3)) 

但下面的錯誤製作,因爲y的默認值設置不正確:

TypeError: multiplyNumbers() missing 1 required positional argument: 'y' 

是否有可能在運行時重新定義函數的默認參數,正如我在這裏試圖做的那樣?

+1

在函數_also_上設置屬性'y'不會改變'y'的默認參數。 – abarnert

回答

21

只需使用functools.partial

multiplyNumbers = functools.partial(multiplyNumbers, y = 42) 

一個問題就在這裏:你就不能稱其爲multiplyNumbers(5, 7, 9);應手動說y=7

如果您需要刪除默認的參數,我們看到有兩種方式:

  1. 將原始功能存儲在某處

    oldF = f 
    f = functools.partial(f, y = 42) 
    //work with changed f 
    f = oldF //restore 
    
  2. 使用partial.func

    f = f.func //go to previous version. 
    
+1

該死的性感。 – joshlf

+0

@ joshlf13,你也可以使用靜態語言。 – RiaD

+0

你的意思是說可以做一些類似的代碼片段?我想這可能是一個足夠強大的類型系統,但我不知道很多這樣的語言。我想,許多功能語言,但我的意思是必要的(雖然我應該明確說)。 – joshlf

0

使用func_defaults作爲

def myfun(a=3): 
    return a 

myfun.func_defaults = (4,) 
b = myfun() 
assert b == 4 

支票func_defaults here

更新文檔:找在RiaD的迴應中,我認爲我對我的評論太過分了。我不知道你問這個問題的背景,但總的來說(並遵循Zen of Python)我相信使用部分應用程序比重新定義函數的默認參數更好的選擇

+0

我沒有設法將它設置爲3個變量中的第二個。只爲我工作最後。 – RiaD

+0

@RiaD:函數默認必須是參數的最終序列;就像你不能寫'def foo(x,y = 2,z):'一樣,你不能將'func_defaults''''__defaults__'改爲覆蓋'y'。 – abarnert

7

從技術上講,有可能按照你的要求做...但這不是一個好主意。 RiaD的回答是Pythonic這樣做的方式。

在Python 3:

>>> def f(x=1, y=2, z=3): 
...  print(x, y, z) 
>>> f() 
1 2 3 
>>> f.__defaults__ = (4, 5, 6) 
4 5 6 

與其他一切封面和硬下是在文檔中找到,該inspect模塊圖是看功能屬性的最佳去處。

Python 2中的細節略有不同,但想法是一樣的。 (只需將文檔頁面左上角的下拉菜單從3.3更改爲2.7即可。)


如果你想知道Python的知道它默認與論據去的時候,它只是有一個元組...它只是向後的端部(或第一**args**kwargs後-anything計數代之以進入__kwdefaults__字典)。 f.__defaults = (4, 5)將默認值設置爲yz45,默認值爲x。這是有效的,因爲在默認參數後你不能有非缺省參數。


有些情況下,這是不行的,但即使是這樣,你可以一成不變它與不同的默認值複製到新的功能:

>>> f2 = types.FunctionType(f.__code__, f.__globals__, f.__name__, 
...       (4, 5, 6), f.__closure__) 

這裏,types module文檔不真正解釋任何事情,但交互式解釋器中的help(types.FunctionType)顯示您需要的參數。


唯一的情況下,你不能手柄內置函數。但是他們通常沒有實際的違約;相反,他們在C API中僞造了類似的東西。

+0

您提到在運行時更改函數的默認參數並不是一個好主意。你有沒有注意到這種方法的缺點? (我還沒有意識到)。 –

+0

@AndersonGreen:有一個明顯的缺點,它會讓你更難,其他人,棉絨,IDE,基於反射的工具,比如'pickle'等來理解你的代碼。你必須完全理解args/params的規則,以確保你做對了。那麼事實上,如果不編寫可以處理常規函數的代碼,不可變的函數(需要從代碼中構造一個新函數)以及內置函數(您需要打包,用一個「部分」或一個新的函數來調用它)。 – abarnert

相關問題