在 Python 中,将不是 Python 标识符的关键字参数传递给函数是否安全?这是一个例子:
>>> '{x-y}'.format(**{'x-y': 3}) # The keyword argument is *not* a valid Python identifier
'3'
>>> '{x-y}'.format(x-y=3)
File "<ipython-input-12-722afdf7cfa3>", line 1
SyntaxError: keyword can't be an expression
我问这个是因为用包含破折号的名称来格式化对我来说更方便(因为这些值对应于名称中带有破折号的命令行参数)。但这种行为是否可靠(即它是否会因 Python 版本而异)?
我不确定官方是否支持使用非标识符作为关键字参数:事实上,documentation阅读:
If the syntax **expression appears in the function call, expression must evaluate to a mapping, the contents of which are treated as additional keyword arguments.
…其中“关键字参数”被定义为具有标识符的名称:
keyword_arguments ::= keyword_item ("," keyword_item)*
keyword_item ::= identifier "=" expression
哪里identifiers限制他们可以使用的字符(-
例如被禁止):
identifier ::= (letter|"_") (letter | digit | "_")*
因此,文档指出在函数调用中给 **
的映射应该只包含有效标识符作为键,但 CPython 2.7 接受更通用的键(对于 format()
和带有 **
参数的函数,它们不会将值放入变量中)。这是一项可靠的功能吗?
最佳答案
首先:具有非标识符名称的 **{...}
调用约定仅在被调用函数具有要接收的 **kw
参数时才有效它们,因为它也不能定义不是有效标识符的显式关键字参数。
我想说 keyword_arguments
语法只适用于源代码的解析器,永远不能被视为对**expression
结果。下面的功能描述并没有明确限制字典的键,function definition documentation也没有。 .
相反,由于语法允许使用表达式
,并且功能规范声明它应该解析为一个映射其内容被视为附加关键字参数,它很明显(对我而言),除了适用于 Python 字典的普通限制之外,对键完全没有任何限制(键必须是不可变的)。您可以为所有 Python 关心传递元组或数字键。功能规范说明如何处理内容,而不是内容必须符合特定格式。
因此,在我看来,功能规范必须显式限制 **expression
字典中的键以禁止您正在做的事情,因为语法确实如此不是。更改那将是一个巨大的向后不兼容的更改,并且不太可能被添加。
请注意,即使规范未提及对字典键的任何限制,CPython 也会:
>>> def f(*args, **kw): print args, kw
...
>>> f(**{1: 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() keywords must be strings
这是 python 解释器在调用代码对象(用户定义的函数)时所做的限制。 the source code 中解释了原因。在引发上述异常的部分之后:
/* Speed hack: do raw pointer compares. As names are
normally interned this should almost always hit. */
通过将关键字限制为字符串,可以优化速度。
关于python - 使用函数接受不是标识符的 kwargs 关键字参数是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39362915/