python - 以 dict 作为参数调用函数
问题描述
我目前正在使用argparse
. 我Namespace
从arg_parse
. 基本上来自 CLI 的参数应该传递给 2 个函数。现在我正在寻找一种聪明的方法来拆分Namespace
这样我可以简单地使用拆包。
下面的例子应该说明我需要什么:
import argparse
ns1 = argparse.Namespace(foo=1)
ns2 = argparse.Namespace(bar=2)
ns3 = argparse.Namespace(foo=1, bar=2)
def f(foo): return foo
def g(bar): return 10 * bar
f(**vars(ns1)) # works
g(**vars(ns2)) # works
f(**vars(ns3)) # does not work, 'bar' is not an argument of f
我可以像这样对过滤器进行硬编码
f_args = ["foo"]
g_args = ["bar"]
f(**{k:v for k, v in vars(ns3).items() if k in f_args}) # works
g(**{k:v for k, v in vars(ns3).items() if k in g_args}) # works
但这感觉很容易出错(如果 的签名f
会改变,我必须记住也要改变f_args
。)。但是,我可以inspect.getfullargspec
用来自动化这部分,例如:
import inspect
f_args = inspect.getfullargspec(f).args
但这一切对我来说都是骇人听闻的,我想知道我是否没有忽略一个简单的模式?
更新
正如@doer_uvc 所指出的,一种方法是使用“catch all”参数来处理我的函数,例如:
def f(foo, **kwargs): return foo
虽然这是一个可行的解决方案,但我很想找到不需要触摸f
自身签名的解决方案。
解决方案
这没有简写。然而,人们可以很容易地使用它来构建它inspect.signature
——这些不是黑客,Python 签名可能会变得非常复杂,并且inspect
只是为了这样的目的而存在。
import inspect
def apply(call: 'Callable', kwargs: 'Dict[str, Any]'):
"""Apply all appropriate ``kwargs`` to ``call``"""
call_kwargs = inspect.signature(call).parameters.keys()
matching_kwargs = {name: kwargs[name] for name in kwargs.keys() & call_kwargs}
return call(**matching_kwargs)
这将检查 预期的参数call
,并选择 提供的参数kwargs
。如果kwargs
缺少任何参数call
,则抛出缺少参数的标准异常。
>>> def f(foo):
... return foo
...
>>> apply(f, {'foo': 2, 'bar': 3})
2
>>> apply(f, {'baz': 2, 'bar': 3})
…
TypeError: f() missing 1 required positional argument: 'foo'
推荐阅读
- reactjs - Ag Grid + React:服务器端 - 添加新行时,网格不会自动更新
- sql-server - 如何将 MS SQL 日期或日期时间转换为 OADate?
- ansible - ansible json_query 多个值
- python - 如何使用特定版本的 python 解释器来运行脚本而不将其安装在系统上?
- php - Laravel:如何在 Excel 导出文件中添加页眉、页脚和徽标图像?
- python - 如何使用递归在python中的数字列表中查找最大数字
- r-exams - r 考试控制错误答案的分数
- jestjs - NestJS- 使用 beforeEach 钩子的 npm 测试非常慢
- google-tag-manager - 在页面上加载元素时触发标签(谷歌标签管理器)
- xml - 使用 Augeas 将新节点添加到 XML 文件