【问题标题】:Python - use dictionary of **kwargs including variables before assignment?Python - 在赋值前使用 **kwargs 字典,包括变量?
【发布时间】:2020-07-02 16:04:42
【问题描述】:

我有一个自定义函数,该函数接受一堆参数,并使用所述参数的不同配置多次调用。为了清洁和易用,我想在所有函数调用之前定义一个参数字典,然后将其作为**kwargs传递给每个调用:

def func(arg1, arg2, arg3, opt_arg4=x, opt_arg5=y, opt_arg6=z):
    do_something

dict1 = {'arg1': 'foo', 'arg2': 'bar', 'arg3': 'baz', 'opt_arg4': 42}
dict2 = {'arg1': 'Ni', 'arg2': 'Peng', 'arg3': 'Neee-Wom', 'opt_arg5': 'yellow'}
dict3 = {'arg1': 'Ni', 'arg2': 'bar', 'arg3': 'Ekke ekke', 'opt_arg6': name}

func(**dict1)
func(**dict2)
func(**dict3)

如果我希望字典中的某些参数是尚未定义的变量,就会出现我的问题。因此,它们将在分配之前被引用,除了在实际使用之前稍后定义的占位符。例如,上面的dict3 包含'opt_arg6': name,其中name 是一个变量,它可以这样使用:

knightlist = ['Lancelot', 'Galahad', 'Robin']
for name in knightlist:
    func(**dict3)

有没有办法做到这一点或达到类似的结果?

编辑: 稍微详细一点,摘自实际代码:

i = 1
for c in c_list: # Where c_list has been read in from input
    compile_func(somedict[c], c, i, {'model': f'_{c}', 'optparm': '_i'}, log=logfile, subdir=c)
# Where somedict and logfile have previously been defined

我希望能够将其替换为:

c_args = {'arg1': somedict[c], 'arg2': c, 'arg3': i, 'arg4': {'model': f'_{c}', 'optparm': '_i'}, 'log': logfile, 'subdir': c}
# With the actual arg names as keys of course

Bunch_of_other_code()

i=1
for c in c_list:
    compile_func(**c_args)

或类似的可分离的东西。希望这更清楚!

编辑 2: 试图解决更根本的问题: 对于一个有很多参数的函数,其中一些是变量或变量的修改,有什么方法可以传递相对整洁、可读和容易修改的参数?特别是如果使用不同的参数集多次调用,我希望能够在代码中的同一位置进行配置?

【问题讨论】:

  • 有什么问题:dict3['opt_arg6'] = name 就在func(**dict3) 之前?
  • @stovfl 请参阅下面的编辑和讨论 - 实际代码涉及更多变量或对其进行修改,因此虽然这会起作用,但它会变得非常混乱,这会破坏我在第一名(比在每个函数调用中输入所有参数更整齐地组织它)。

标签: python python-3.x function


【解决方案1】:

将显式关键字参数与解包混合。从dict3 中删除'opt_arg6',然后这样做:

for name in knightlist:
    func(opt_arg6=name, **dict3)

除此之外,最接近您尝试做的是定义一个生成您想要的dict 的函数,并在您需要dict 时调用它。这根本不会提高性能(因为每次仍会重新生成dict),但可以想象它可能会稍微简化您的调用代码。与您的第二个代码示例匹配的示例将 c_args 的定义替换为:

def make_c_args(c, i):
    return {'arg1': somedict[c], 'arg2': c, 'arg3': i, 'arg4': {'model': f'_{c}', 'optparm': '_i'}, 'log': logfile, 'subdir': c}


Bunch_of_other_code()

i=1
for c in c_list:
    compile_func(**make_c_args(c, i))

如果函数在同一范围内并且可以从其自身的外部范围访问ci,则可以避免接受和传递ci

类似的方法是为您的compile_func 编写一个包装器,它执行必要的c 工作,从传递给compile_func 的所有相关显式关键字参数扩展为显式c。在所有情况下,您确实必须做所有相同的工作;如果不推迟 dict 的创建,直到惰性值实际上急切可用,就不可能以您想要的方式拥有具有惰性评估值的 dict

【讨论】:

  • 这会起作用,但是(示例代码当然是简化的)在某些情况下,我希望多个参数是变量或同一个变量,足以按照您的建议混合它们会在某种程度上破坏首先解包的目的(即可读性和易于修改),因为它仅比仅在函数调用中指定参数好一点。有没有一种方法可以更优雅/更简洁地传递参数?
  • @TYLim:我需要一个更完整的例子来提出任何建议;您正在描述一个非常复杂的场景,没有更好的解决方案,但它可能具有完全依赖于您省略的细节的快捷方式。通常这样的情况有点an XY problem
  • 从上面的实际代码中添加了一些细节,希望让它更清楚一点......我知道它解决了一个更基本的架构问题,我已经previously asked aboutnot always successfully...
  • @TYLim:是的,你的问题没有任何神奇的解决方案。你必须每次都做这项工作;您所能做的就是通过使用辅助函数来完成您不想在“其他地方”做的工作,从而将其从调用站点中隐藏起来。
  • 知道了……这并不完全出乎意料。作为一个相对新手,我总是在发现更多新的“神奇解决方案”,所以总是想知道我是否遗漏了一些东西,但“没有简单的解决方案”也是一个有用的答案。感谢理解!
猜你喜欢
  • 2020-07-28
  • 2019-04-15
  • 2014-01-10
  • 2018-04-19
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 2015-08-04
  • 2021-03-13
相关资源
最近更新 更多