将Partial与条件默认参数一起使用

时间:2018-12-12 18:36:13

标签: python python-3.x lambda functools

我在库函数上使用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。例如,我们在字典中查找带有不同y值的键的z。

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])

但是会出错(有充分的理由!)

2 个答案:

答案 0 :(得分:4)

您可以改用包装函数:

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)

答案 1 :(得分:1)

否,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