使用可以接受不是标识符的kwargs关键字参数的函数安全吗? [英] Is is safe to use a function accepts kwargs keyword arguments that are not identifiers?

查看:92
本文介绍了使用可以接受不是标识符的kwargs关键字参数的函数安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Python中,将不是 Python标识符的关键字参数赋予函数是否安全?这是一个示例:

In Python, is it safe to give keyword arguments that are not Python identifiers to a function? Here is an example:

>>> '{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版本之间会有所不同)吗?

I am asking this because it is more convenient for me to format with names that contain a dash (because the values correspond to command-line argument with dashes in their name). But is this behavior reliable (i.e. can it vary between version of Python)?

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

I am not sure that using non-identifiers as keyword arguments is officially supported: in fact, the documentation reads:

如果语法** expression出现在函数调用中,则expression 必须评估为映射,其内容被视为 其他关键字参数.

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.

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

… where "keyword arguments" are defined as having a name which is an identifier:

keyword_arguments :: = keyword_item(," keyword_item)*

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

keyword_item :: =标识符"="表达式

keyword_item ::= identifier "=" expression

其中标识符的字符受限制可以使用(例如,-被禁止):

where identifiers are restricted in what characters they can use (- is for instance forbidden):

标识符:: =(字母|"_")(字母|数字|"_")*

identifier ::= (letter|"_") (letter | digit | "_")*

因此,文档表明在函数调用中给**的映射应仅包含有效的标识符作为键,但是CPython 2.7接受更多通用键(对于format()和带有**参数的函数,不要将值放在变量中).这是可靠的功能吗?

So, the documentation indicates that the mapping given to ** in a function call should only contain valid identifiers as keys, but CPython 2.7 accepts more general keys (for format() and functions with a ** argument, which do not put values in variables). Is this a reliable feature?

推荐答案

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

First of all: the **{...} call convention with non-identifier names only works if the called function has a **kw argument to receive them, as it too cannot define explicit keyword arguments that are not valid identifiers.

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

I'd say that the keyword_arguments grammar only applies to the parser of the source code, and cannot ever be seen as a functional restriction on the contents of the **expression result. The functional description below does not restrict the keys of the dictionary explicitly, nor does the function definition documentation.

相反,由于语法允许使用expression,并且功能规范指出应解析为映射的映射,因此其内容被视为其他关键字参数,这很明显(对我来说),除了适用于Python字典的普通键(键必须是不可变的)以外,键 上没有任何限制.您可以为所有Python护理传递元组或数字键.功能规范说明了内容的处理方式,而不是内容必须符合特定格式.

Instead, since the grammar allows an expression, and the functional spec states that that should resolve to a mapping the contents of which are treated as additional keyword arguments, it is clear (to me) that there are no restrictions on the keys at all, beyond the normal ones applicable to Python dictionaries (keys must be immutable). You can pass in tuple or numeric keys for all Python cares. The functional spec states how the contents are treated, not that the contents must fit a certain format.

所以,我认为功能规范必须明确限制**expression词典中的键以禁止您正在执行的操作,因为语法肯定不会.更改将是一个巨大的向后不兼容的更改,并且不可能再添加.

So, in my opinion the functional spec would have to explicitly restrict the keys in the **expression dictionary to disallow what you are doing, because the grammar certainly does not. Changing that would be a huge backwards-incompatible change, and is not likely to ever be added.

请注意,即使规范未提及字典键的任何限制,CPython也会:

Note that even though the spec doesn't mention any restrictions on the keys of the dictionary, CPython does:

>>> 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解释器在调用代码对象(用户定义的函数)时做出的限制.紧随其后的是源代码中说明的原因引发上述异常的部分:

This is a restriction made by the python interpreter when invoking code objects (user defined functions). The reason why is explained in the source code right after the part that raises the above exception:

/* Speed hack: do raw pointer compares. As names are
   normally interned this should almost always hit. */

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

By restricting keywords to strings a speed optimisation is possible.

这篇关于使用可以接受不是标识符的kwargs关键字参数的函数安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆