代码之家  ›  专栏  ›  技术社区  ›  Greedo

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

  •  3
  • Greedo  · 技术社区  · 6 年前

    我在用 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不是一个常量的默认z,而是依赖于y的值。例如,我们在字典中查找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])
    

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

    2 回复  |  直到 6 年前
        1
  •  4
  •   blhsing    6 年前

    您可以改用包装函数:

    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
  •  1
  •   jpp    6 年前

    否,默认值为 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