Python函数中的kwargs参数的键是否保证为字符串类型?

10
def func(**kwargs):
   for key, value in kwargs.items():
      # Is key always going to be a string?
      # Could it have spaces?
      pass

关于Python中kwargs的两个问题。

  1. kwargs的每个键是否保证为str类型?如果是,则我可以避免类型检查。
  2. 如果#1成立,那么每个键是否保证不含空格?

2
相关:[为什么在使用**时,Python接受无效名称作为关键字参数?- Reddit](https://www.reddit.com/r/Python/comments/33fid7/why_does_python_accept_invalid_names_as_keyword/) - wjandrea
只是为了明确,我关心的两个问题是: 1)kwargs中的键是否为str类型? 2)kwargs中的键是否可以有空格? - engineerchuan
如果您想要,您可以[编辑]这个问题。 - wjandrea
关键字必须仅包含字符串,并且所有键必须是唯一的。- abstract.h _PyVectorcall_Function - wwii
PyArg_ValidateKeywordArguments(PyObject *kwargs) ... if (!_PyDict_HasOnlyStringKeys(kwargs)) {... - 在getargs.c中 - wwii
3个回答

14
直接传递的关键字参数必须是有效的Python标识符,而且它始终会被视为字符串。其他任何内容都会导致"SyntaxError"错误。

直接傳遞的關鍵字參數必須是有效的 Python 標識符,也會始終被視為字符串。任何其他內容都會導致 "SyntaxError" 錯誤。

f(foo=1) # Works
f($=1) # Fails
f(1=1) # Fails

虽然你也可以通过解包来传递关键字参数。在这种情况下,你的关键字参数仍然必须是字符串,但可以采用任何格式。

让我们定义一个虚拟函数来测试它。

def f(**kwargs):
    print(kwargs)

一个关键字参数可以包含空格或由数字组成的字符串。它甚至可以包含特殊字符。

f(**{"hello world": 'foo'}) # prints {'hello world': 'foo'}
f(**{"1": 'foo'}) # prints {'1': 'foo'}
f(**{"$": 'foo'}) # prints {'$': 'foo'}

关键字参数必须是字符串。其他任何类型都会导致 TypeError 错误。

f(**{1: 'foo'}) # TypeError: f() keywords must be strings
f(**{b'foo': 1}) # TypeError: f() keywords must be strings

语言参考中的表达式部分讲解了调用,其中提到参数被放置在插槽中 - 也许这些是 __slots__?对象的 __slots__ 看起来只能使用字符串。 - wwii
@wwii: 不,我很确定文档中提到的插槽与__slots__无关,除了它们代表相似的概念并且被赋予了相同的名称。 __slots__机制涉及类实例的属性,而不是函数调用。 - Blckknght

3
kwargs 中的 keywords 应该遵循变量名的规则,full_name 是一个有效的变量名(也是一个有效的keyword),而 full name 不是一个有效的变量名(也不是一个有效的keyword)。
来自 PEP 362 -- Function Signature Object

Parameter 对象具有以下公共属性和方法:
name : str
- 参数的名称作为字符串。必须是一个有效的 Python 标识符名称(除了 POSITIONAL_ONLY 参数,它可以被设置为 None)。

并且,来自 Docs

2.3. Identifiers and keywords:
... 在 ASCII 范围内(U+0001..U+007F),标识符的有效字符与 Python 2.x 相同:大写字母 AZ、下划线 _ 和除了第一个字符以外的数字 09。 ...


1
也许可以参考官方的Python文档,其中提到“参数名称必须是一个有效的Python标识符字符串”。而programiz中则指出,“标识符可以由小写字母(a到z)、大写字母(A到Z)、数字(0到9)或下划线(_)组成”。 - Rickyy
@OlivierMelançon 这里指的是 kwargs 的名称。 - juanpa.arrivillaga
3
不可以。在函数的签名和调用中,如果使用显式的关键字参数,例如 f(..., key=value),那么 key 必须是一个有效的标识符名称。但是,如果像您所做的那样使用字典解包来调用函数,则可以使用任意字符串作为键。 - GZ0
3
Python允许使用任意字典作为**kwargs传递。我不知道为什么他们不会验证kwarg的名称,但在使用int作为关键字时抛出TypeError。这个问题在2013年已经被讨论过了 - feature: **kwargs allowing improperly named variables - Rickyy
谢谢,这很有道理。但是对于kwargs参数,允许使用空格。我稍微澄清一下我的问题。 - engineerchuan

1
其他人已经涉及了实际方面,但我想知道文档是否有关于关键词字典类型的保证。调用语义的文档没有明确表示关键字参数将在字典中具有str类型。
文档只是这样描述以**声明参数的关键字参数值类型:
一个包含多余关键字参数(使用关键字作为键和参数值作为对应值)的字典,或(新的)空字典。
因此,理论上,文档允许您接收关键字参数作为bytes,但这不会发生在任何现有的Python 3实现中。(对于Python 2,情况相同,但是使用unicode 而不是bytes。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接