是否安全使用函数接受不是标识符的kwargs关键字参数?

Eri*_*got 6 python identifier python-2.x keyword-argument python-3.x

在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
Run Code Online (Sandbox Code Playgroud)

我问这个是因为使用包含破折号的名称格式化更方便(因为这些值对应于名称中带有破折号的命令行参数).但这种行为是否可靠(即它可以在Python版本之间变化)?

我不确定是否正式支持使用非标识符作为关键字参数:实际上,文档中包含:

如果语法**表达式出现在函数调用中,则表达式必须求值为映射,其内容被视为附加关键字参数.

...其中"关键字参数"被定义为具有作为标识符的名称:

keyword_arguments :: = keyword_item(","keyword_item)*

keyword_item :: = identifier"="表达式

其中标识符在它们可以使用的字符限制(-例如是禁止的):

identifier :: =(letter |"_")(字母|数字|"_")*

因此,文件表明,给予映射**函数调用中应该只包含合法的标识符作为键,但CPython的2.7接受更广泛的键(format()和功能与**参数,它不把值变量).这是一个可靠的功能吗?

Mar*_*ers 5

首先:**{...}具有非标识符名称的调用约定仅在被调用函数具有**kw接收它们的参数时才有效,因为它也无法定义不是有效标识符的显式关键字参数.

我会说keyword_arguments语法只适用于源代码的解析器,并且不能被视为对**expression结果内容的功能限制.下面的功能描述不会明确限制字典的键,也不会限制函数定义文档.

相反,因为语法允许的expression,功能规范规定,应该可以解决的映射,其中被视为额外的关键字参数的内容,很显然(对我)有上的按键没有任何限制可言,超越适用于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
Run Code Online (Sandbox Code Playgroud)

这是python解释器在调用代码对象(用户定义的函数)时所做的限制.在引发上述异常的部分之后的源代码中解释了原因:

/* Speed hack: do raw pointer compares. As names are
   normally interned this should almost always hit. */
Run Code Online (Sandbox Code Playgroud)

通过将关键字限制为字符串,可以实现速度优化.

  • kw dict键*do*必须是字符串:尝试`def foo(**kw):pass; foo(**{1:5})` 这在Python 2.7和3.3中给出了一个`TypeError`. (3认同)
  • @lvc,kw dict键必须是字符串,除了在格式方法中它们不是''{xy}'.格式(**{'x-y':3,4:5})`不抛出预期的异常. (2认同)
  • 是的,如果我今天晚些时候有时间,我将完成提交历史,看看我能挖掘出什么. (2认同)