12
>>> 'string with no string formatting markers' % ['string']
'string with no string formatting markers'
>>> 'string with no string formatting markers' % ('string',)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting

どちらの場合もが発生すると思いTypeErrorますが、そうではありません。なぜだめですか?

このテーマに関するPythonのドキュメントでは、文字列、タプル、辞書について説明していますが、リストについては何も述べていません。私はこの振る舞いについて少し混乱しています。Python2.7と3.2で複製することができました。

4

1 に答える 1

6

注意深く読むと、ドキュメントには次のように記載されています。

formatに単一の引数が必要な場合、値は単一の非tuple オブジェクトである可能性があります。それ以外の場合、値はtuple、フォーマット文字列で指定された正確な数のアイテム、または単一のマッピングオブジェクト(辞書など)である必要があります。

さて、この場合、formatは単一の引数を必要としないため、ドキュメントには、tuple引数としてまたはマッピングを使用する必要があると記載されています。他のケースは「未定義の振る舞い」に分類されます(これが起こっていることです:振る舞いはすべてのケースで一貫しているわけではありません)。

これはおそらく、質問に対する最終的な答えと見なす必要があります。文字列にフォーマット指定子がない場合、list(またはマッピングとは異なる種類のtuple)を使用すること自体が、未定義の動作につながるバグと見なす必要があります。

このことから、常にtupleまたはを引数として使用する必要dictがあります。そうしないと、フォーマット指定子を手動でチェックするか、奇妙な動作を処理する必要があります。

あなたの場合、おそらくの(['string'], )代わりにを使用して問題を修正できます['string']


結果として生じる動作が非常にランダムに見える理由の考えられる「説明」:

の行で使用する代わりに、/の元の実装にバグのあるチェックがあったようです。PyString_FormatPyUnicode_FormatPyMappingCheck

if (PyMapping_Check(args) && !PyTuple_Check(args) &&
     !PyObject_TypeCheck(args, &PyBaseString_Type))
    dict = args;

このコードが使用されました:

if (Py_TYPE(args)->tp_as_mapping && !PyTuple_Check(args) &&
    !PyObject_TypeCheck(args, &PyBaseString_Type))
    dict = args;

これは同等ではありません。たとえば、(少なくとも数週間前にダウンロードしたPython2.7.3ソースコードでは)設定されsetていませんが、設定されています。tp_as_mappinglist

これが、(そしておそらく他のオブジェクトが) while 、、、および他の多くlistのオブジェクトを上げない理由かもしれません。TypeErrorsetint

この同じ答えで前に述べたように、私はsTypeErrorでも得ますlist

$ python2
Python 2.7.3 (default, Sep 26 2012, 21:53:58) 
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 'some string' % []
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting

これはおそらく、上記の問題だけがここにあるのではないことを示しています。

ソースコードを見ると、理論的には、引数がタプルでない場合は引数の数がチェックされないことに同意しますが、これは暗黙的'some string' % 5 -> 'some string'であり、ではないTypeErrorため、そのコードには何か怪しいものがあるはずです。

于 2012-12-13T16:58:01.950 に答える