【问题标题】:Getting a dictionary of all named arguments passed to a method获取传递给方法的所有命名参数的字典
【发布时间】:2022-08-04 03:29:50
【问题描述】:

我有多种方法都可以构建在subprocess 中运行的 bash 命令。它们都是不同的,但具有相同的基本逻辑。如果True,则所有布尔关键字必须转换为--myBool,如果不为空或None等,则所有字符串必须转换为--myStr=content_of_myStr。具有特定类型(列表等)的其他参数在每个中单独处理方法。

我想为用户保留一些类型提示(基本和常用关键字),同时允许用户将使用范围扩展到其他不常见的关键字(通过**kwargs),最重要的是,我想保留一些关键字的默认值。如果将所有命名参数放在**kwargs 中,我想我无法满足这些需求。

如何自动获取传递给方法的所有对 key: value 的字典(在签名中明确命名加上 **kwargs 中的那些)?当然,我的请求不能支持签名中的*args

例如:

def my_func(a, b, c=3, **kwargs):
    print(_some_magic_function_)

my_func(a=1, b=2, d=4)
# {\'a\': 1, \'b\': 2, \'c\': 3, \'d\': 4}

一种解决方案是这样做:

def my_func(**kwargs):
    print(kwargs)

my_func(a=1, b=2, d=4)
# {\'a\': 1, \'b\': 2, \'d\': 4}

但这样,我无法处理默认值,也没有给用户的类型提示。

  • 是什么目的这个的?例如,您可以简单地 print(dict(a=a, b=b, c=c, **kwargs)),但不知道为什么很难说这是否满足您的需求。
  • ^ 乔恩所说的。当心XY problem
  • @jonrsharpe 我希望该解决方案适用于所有方法,而无需硬编码 \'a\'、\'b\' 等。
  • @jonrsharpe - 这不是如何进行 **kwargs 关键字扩展但仍有类型提示的问题吗?当然,您可以构建自己的 dict,但有没有办法不必这样做?
  • @tdelaney 我不知道;这就是我问OP的原因。

标签: python


【解决方案1】:

您正在寻找的似乎主要是通过使用 locals() 来解决的,这可能是够好了为您解决。

然而, locals() 不给你函数参数,而是给你局部变量。特别是在某些情况下,即使作为函数中的第一条指令调用,locals() 也会给出更多的.例如:

class A:
    def f(self, a=1):
        print(locals())
        print(f"Hello from {__class__}!")
        
A().f()

印刷

{'self': <__main__.A object at 0x000002266A0659C0>, 'a': 1, '__class__': <class '__main__.A'>}
Hello from <class '__main__.A'>!

即使您可能期望它会打印

{'self': <__main__.A object at 0x000002266A0659C0>, 'a': 1}
Hello from <class '__main__.A'>!

我不确定编译器可以插入多少这些鬼鬼祟祟的额外本地人,__class__ 是我所知道的唯一一个,所以这真的取决于你想要变得多么强大。

选项 1:如果编译器没有插入偷偷摸摸的 __class__ 变量(如果您在方法中的任何地方使用 __class__super 会发生这种情况)。

print(locals())

选项 2:只要您不使用参数覆盖偷偷摸摸的 __class__ 变量即可。

print({k: v for k, v in locals().items() if k != `__class__`})

选项 3:看起来最强大但也最可怕。

import inspect
sig_params = inspect.signature(A.f).parameters
print({k: v for k, v in locals().items() if k in sig_params}

【讨论】:

    【解决方案2】:

    最后,感谢 mCoding 的回答,这是我使用的代码:

    loc = locals()
    loc.update(loc.pop('kwargs'))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-19
      • 1970-01-01
      • 2012-12-12
      • 2012-10-22
      • 2011-03-18
      • 1970-01-01
      • 2012-05-30
      • 1970-01-01
      相关资源
      最近更新 更多