使用带条件默认参数的部分

Posted

技术标签:

【中文标题】使用带条件默认参数的部分【英文标题】:Using partial with a conditional default argument 【发布时间】:2019-05-13 22:20:01 【问题描述】:

我在库函数上使用partial 为其中一个参数提供默认值

library_func = lambda x, y, z : x + y + z

my_func = functools.partial(library_func, z = 5) #default value for one of the variables
# equiv to lambda x, y : x + y + 5

现在假设我希望 z 依赖于 y 的值,而不是一个恒定的默认 z。例如,我们在字典中查找 z,其中的键是 y 的不同值。

z = "1":7,"2":8[str(y)]

# now my_func(x,y) = library_func(x,y,z = f(y))

这可能吗?在我的用例中,我有一个类持有与数据库的连接 (self.engine)

    self.engine = sqlalchemy.create_engine(connection_string)
    self.read_sql = partial(pd.read_sql, con = self.engine)

pd.read_sql 的签名类似于pd.read_sql(con , name, columns ...)

我想为取决于传递的名称值的列设置默认值。

我想过

self.read_sql = partial(pd.read_sql, con = self.engine, columns = lambda name: self.name_to_column_dict[name])

但得到错误(有充分的理由!)

【问题讨论】:

我认为最简单的方法是定义一个简单的包装函数,它采用xy,准备z 并调用您的库函数。 @Wombatz 是的,但如果我这样做,我是否必须手动输入所有参数?这似乎有点绕房子 包装函数或装饰器对我来说似乎是最好的。避免使用functools.partial,除非是最琐碎的情况。 @wim 不希望遇到太新手,我喜欢使用部分函数的一个重要原因是因为它保留了 Jupyter Notebook Intellisense/autocomplete 中的所有文档字符串和关键字 arg 内容。但正如你所说,也许对于更复杂的情况,你自己动手会更容易。 要保留文档字符串,您可以使用functools.wraps 【参考方案1】:

您可以改用包装函数:

def my_func(x, y):
    return library_func(x, y, "1":7,"2":8[str(y)])

或者,如果您不想按照评论中的建议重新键入所有关键字参数,您可以使用inspect.signature 获取包装函数的签名,然后将传入的参数绑定到参数,以便您可以使用 dict 键访问它们,无论参数是作为位置参数还是作为关键字参数传入:

import inspect

def my_func(*args, **kwargs):
    bound = sig.bind(*args, **kwargs)
    bound.apply_defaults()
    return library_func(**bound.arguments, z="1":7,"2":8[str(bound.arguments['y'])])

sig = inspect.signature(my_func)

【讨论】:

啊,我明白了,这是一种方法。但是有没有一些不涉及重新输入所有参数的方法? 我已经用一个解决方案更新了我的答案,该解决方案有助于避免重新输入包装器中的所有关键字参数。【参考方案2】:

不,partial 函数的默认值在调用函数之前进行评估。

理想情况下,您可以修改库函数:

def library_func(x, y, z=None):
    if z is None:
        z = '1': 7, '2': 8[y]
    return  x + y + z

但如果这不可能,您可以使用包装函数:

def library_func(x, y, z):
    return  x + y + z

def library_func_wrapper(*args):
    return library_func(*args, '1': 7, '2': 8[str(args[-1])])

res = library_func_wrapper(6, 2)  # 16

【讨论】:

以上是关于使用带条件默认参数的部分的主要内容,如果未能解决你的问题,请参考以下文章

默认容器参数

类模板参数带默认值

关于python带默认值的参数只能放在后面的问题

windows设置默认程序如何带参数

带默认参数的模块导出

ReadProcessMemory函数的参数如何设置