[英]Redefine defaults arguments of a python function by name
出於效率目的,我不想為此任務使用functools.partial
(使用該函數時會增加開銷)。 我想按名稱重新定義函數的副本默認值 arguments。
目前我有以下內容:
import types
# http://stackoverflow.com/questions/6527633/how-can-i-make-a-deepcopy-of-a-function-in-python
def copy_func(f, name=None, defaults=None):
return types.FunctionType(f.__code__, f.__globals__, name or f.__name__, defaults or f.__defaults__, f.__closure__)
def f(a, b, c):
return 'a = {}, b = {} and c = {}'.format(a,b,c)
i = copy_func(f, 'i', (4,5))
print(f(3,4,5))
print(i('should be a'))
我們可以修改copy_func
工具,像這樣調用嗎:
i = copy_func(f, a = 4, b = 5)
即,使用來自原始 function 的 arguments 的名稱。
當然,如果 arguments 不存在,我希望 function 對我大喊大叫;)
我相信你可以做到這一點:
import inspect
def copy_func(f, name=None, **defaults):
args = inspect.getfullargspec(f).args
arg_defaults = tuple(defaults.get(arg) for arg in args)
return types.FunctionType(f.__code__, f.__globals__, name or f.__name__, arg_defaults or f.__defaults__, f.__closure__)
由於我們需要為FunctionType
的默認值提供一個tuple
( arg_defaults
),我們可以通過迭代f
的 arguments 並查看哪些在defaults
中提供了默認值來生成這個tuple
。 我們使用defaults.get
而不是defaults[...]
,因為FunctionType
None
默認值。
copy_func(f, 'i', a = 4, b = 5)()
結果是:
'a = 4, b = 5 and c = None'
如果您希望 function 在defaults
包含無效參數時對您大喊大叫,則需要在args
和arg_defaults
的聲明之間添加此顯式條件:
if not all(arg in args for arg in defaults.keys()):
raise ValueError("defaults contains invalid arguments")
我發現的解決方案不是最好的,但它是一些解決方案。
import types
def copy_func(f, name=None, defaults=None):
return types.FunctionType(f.__code__, f.__globals__, name or f.__name__, defaults=None, f.__closure__)
def f(a, b, c):
return 'a = {}, b = {} and c = {}'.format(a,b,c)
i = copy_func(f, defaults=(4, 5, 0))
該解決方案也將取代 c,這是它的壞處。 我找不到可以為a
和b
設置默認值而不為c
設置默認值的解決方案。 希望這個解決方案也適用。
PS 說實話,我自己不會用這種設置默認值。 此外,我不會復制 function 本身,而是會為f
編寫一個包裝器 function 。
PPS 我希望你能找到一個更好的解決方案,這對我來說也會很有趣。
您正在尋找的是所謂的Method Overloading
。 不幸的是 Python 不支持方法重載。 但是您可以使用許多邏輯方式來實現它。
處理方法重載的幾種方法如下所示
def copy_func(f, name=None, defaults=None):
if name not None:
return types.FunctionType(f.__code__, f.__globals__, name or f.__name__,
defaultsor f.__defaults__, f.__closure__)
if defaults not None:
# add another logic for handling function with defaults as parameter
def copy_func(f, name=None, *defaults):
for x in defaults:
# handle extra parameters here
雖然以上兩種方式都可以正常工作,但是以上兩種方式我們只是處理function的參數來實現方法重載。 如果您真的想定義兩個函數並為它們編寫不同的邏輯而不檢查基於 arguments 的條件。 您應該使用 pip 的multipledispatch
調度 package。
from multipledispatch import dispatch
@dispatch(str,None,None)
def copy_func(f, name=None, defaults=None):
return types.FunctionType(f.__code__, f.__globals__, name or f.__name__, defaults
or f.__defaults__, f.__closure__)
@dispatch(str,str,str)
def f(a, b, c):
return 'a = {}, b = {} and c = {}'.format(a,b,c)
此方法的唯一問題是您必須安裝第三方 package,但它允許您在 Python 中實際使用方法重載,它可以節省您編寫 if 條件和解析 **kwargs 的音調
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.