簡體   English   中英

按名稱重新定義 python function 的默認 arguments

[英]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包含無效參數時對您大喊大叫,則需要在argsarg_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,這是它的壞處。 我找不到可以為ab設置默認值而不為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

使用關鍵字 arguments

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM