7

私は最近Pythonジェネレーターを少し実験していて、次の奇妙な動作に出くわしました。なぜこれが発生し、何が起こっているのかを理解したいと思っています。

def generating_test(n): 
    for a in range(n): 
        yield "a squared is %s" % a*a # Notice instead of a**2 we have written a*a

for asquare in generating_test(3): 
    print asquare 

出力:

a squared is 1
a squared is 2a squared is 2

期待される出力を生成する次のスクリプトと比較してください。

def generating_test(n): 
    for a in range(n): 
        yield "a squared is %s" % a**2 # we use the correct a**2 here

for asquare in generating_test(3): 
    print asquare 

出力:

a squared is 0
a squared is 1
a squared is 4
4

3 に答える 3

20

これはジェネレーターとは何の関係もありません。

>>> a = 2
>>> "a squared is %s" % a
'a squared is 2'
>>> ("a squared is %s" % a)*a
'a squared is 2a squared is 2'
>>> "a squared is %s" % a*a
'a squared is 2a squared is 2'
>>> "a squared is %s" % (a*a)
'a squared is 4'

%opは、文字列と最初の文字列を引数として使用して、乗算の前に実行さaれます。引数付きおよび引数としてのopが。の前に評価されるa**2ため、作業が完了します。**a2%

于 2012-08-07T14:12:19.940 に答える
8

Pythonの操作の順序は、PEMDASが適用される場合を除いて、左から右です。文字列補間演算子は、モジュロおよび乗算と同じ優先順位を持っているようです。順序を逆にして、補間の左側に乗算を行うと、次のように優先されるためです。

>>> print 3 * "a foo %s" % 'hi'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not enough arguments for format string
>>> print 3 * "a foo %s" % ('hi', 'ho', 'yo')
a foo hia foo hoa foo yo

ただし、説明したように、べき乗は左から右の順序よりも優先されます。

更新:Binary Arithmetic Operationsの同じドキュメントで、一目瞭然ですが、一律に関連性があると述べています。

…%演算子は、文字列フォーマット(補間とも呼ばれます)を実行するために文字列およびUnicodeオブジェクトによってオーバーロードされます。

%これは、演算子何をするかを示しているように見えますが、その位置とコンテキストも、モジュロとして使用されているか補間として使用されているかにかかわらず、同じ優先順位を持っていることを示していると思います。

于 2012-08-07T14:21:29.633 に答える
5

予期しない動作を観察した場合は、可能な限り単純なケースに抽出することから分析を開始します。単純なケースは、研究と理解が容易になります。

予期しない動作:

>>> 'hello %s' % 3 * 2
'hello 3hello 3'

(あなたは期待していまし'hello 6'た)


Pythonはコマンドを'hello 3' * 2ではなくとして解釈する必要があると考えてい'hello %d' % 6ます。2番目の解釈を角かっこで強制してみます

>>> "hello %s" % (3*2)
'hello 6'

ユーレカ!

文字列の書式設定演算子%は、乗算よりも優先されることを示しました。Pythonのドキュメントを確認します-はい、これは http://docs.python.org/reference/expressions.html#summaryを確認します

優先順位が等しいことを確認するために、逆の方法で試すことができます。

>>> "%d,"*2%(1,2)
'1,2,'

カンマ(、)が重複していることを確認すると"%d," * 2、文字列のフォーマットの前に乗算が実行されたと考えられます%。乗算が文字列のフォーマットに先行する可能性があり、文字列のフォーマットが乗算に先行する場合、それらは優先順位が等しくなければなりません。

于 2012-08-07T14:34:15.443 に答える