6

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 のバージョン間で異なる可能性があります)?

キーワード引数として非識別子を使用することが正式にサポートされているかどうかはわかりません。実際、ドキュメントには次のように書かれています。

構文 **expression が関数呼び出しにある場合、expression はマッピングに評価される必要があり、その内容は追加のキーワード引数として扱われます。

…ここで、「キーワード引数」は、識別子である名前を持つものとして定義されます。

キーワード引数 ::= キーワード項目 ("," キーワード項目)*

keyword_item ::= 識別子 "=" 式

識別子は、使用できる文字が制限されています (-たとえば、禁止されています)。

識別子 ::= (文字 |"_") (文字 | 数字 | "_")*

そのため、ドキュメントでは**、関数呼び出しで指定されたマッピングにはキーとして有効な識別子のみを含める必要があることを示していますが、CPython 2.7 はより一般的なキー (変数に値を入れない引数をformat()持つ関数) を受け入れます)。**これは信頼できる機能ですか?

4

1 に答える 1

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

これは、コード オブジェクト (ユーザー定義関数) を呼び出すときに Python インタープリターによって行われる制限です。上記の例外が発生する部分の直後のソースコードで理由が説明されています。

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

キーワードを文字列に制限することで、速度の最適化が可能です。

于 2013-06-06T08:23:07.317 に答える