8

たとえば、JavaScriptでは、次のようなプログラムを作成できます。

var a = 1;
testFunction(++a, ++a, a);
function testFunction(x, y, z){
      document.writeln("<br />x = " + x);
      document.writeln("<br />y = " + y);
      document.writeln("<br />z = " + z);
}

そして、出力を取得します。

x = 2
y = 3
z = 3

これは、JavaScriptでパラメータが左から右に真に評価されることを意味します。Cでは出力を取得します

x = 3
y = 3
z = 3

Pythonでも同じことができるのか、それとも値渡し参照言語なので不可能なのか、疑問に思っていました。

私は簡単なプログラムを作成しましたが、それが何も証明していないと思います。

x = 2
def f(x, y, z):
    print(x, y, z)

f(x*2, x*2, x**2)
print(x)
4 4 4
2

Pythonでは、関数パラメーターを呼び出すときに、関数パラメーター内で新しい割り当てを行うことはできません(たとえばf(x=4, x, x)、このようなもの)。

4

6 に答える 6

13
>>> def f(x, y): pass
...
>>> f(print(1), print(2))
1
2
于 2012-10-05T15:27:00.287 に答える
4

関数呼び出しを分解します。

>>> def foo():
...   bar(x+1, x+2, x+3)
... 
>>> dis.dis(foo)
  2           0 LOAD_GLOBAL              0 (bar)
              3 LOAD_GLOBAL              1 (x)
              6 LOAD_CONST               1 (1)
              9 BINARY_ADD          
             10 LOAD_GLOBAL              1 (x)
             13 LOAD_CONST               2 (2)
             16 BINARY_ADD          
             17 LOAD_GLOBAL              1 (x)
             20 LOAD_CONST               3 (3)
             23 BINARY_ADD          
             24 CALL_FUNCTION            3
             27 POP_TOP             
             28 LOAD_CONST               0 (None)
             31 RETURN_VALUE        
于 2012-10-05T15:26:38.817 に答える
4

Python 3の使用:

>>> a = []
>>> f = print(
    a.append(1), a[:],
    a.append(2), a[:],
    a.append(3), a[:]
)
None [1] None [1, 2] None [1, 2, 3]

記録:

>>> a = []
>>> f = print(a.append(1), a, a.append(2), a, a.append(3), a)

不思議なことに(最初は)、このコードは次のように生成します。

None [1, 2, 3] None [1, 2, 3] None [1, 2, 3]

ただし、dis(f)これはより明確になります。

>>> dis(f)

  1           0 LOAD_NAME                0 (print) #Loads the value of 'print' into memory. Precisely, the value is pushed to the TOS (Top of Stack)
    -->       3 LOAD_NAME                1 (a) #Loads the value of object 'a' 
              6 LOAD_ATTR                2 (append) #Loads the append attribute (in this case method)
              9 LOAD_CONST               0 (1) #Loads the constant 1
             12 CALL_FUNCTION            1 #a.append(1) is called
             15 LOAD_NAME                1 (a) #for print(...,a,...)
             18 LOAD_NAME                1 (a) #for the next a.append()
             21 LOAD_ATTR                2 (append) 
             24 LOAD_CONST               1 (2) 
             27 CALL_FUNCTION            1 #a.append(2)
             30 LOAD_NAME                1 (a) 
             33 LOAD_NAME                1 (a) 
             36 LOAD_ATTR                2 (append) 
             39 LOAD_CONST               2 (3) 
             42 CALL_FUNCTION            1 #a.append(3)
             45 LOAD_NAME                1 (a) #loads a to be used thrice by print
             48 CALL_FUNCTION            6 #calls print
             51 PRINT_EXPR                 #prints TOS and clears it
             52 LOAD_CONST               3 (None) #Loads None
             55 RETURN_VALUE             #Returns None

の出力dis(f)は、私たちが期待したものです-L-to-R評価。基本的に、この「不一致」はprint()最後に評価された結果です。それまでに、の値はaに変更され[1, 2, 3]、同じ最終オブジェクトが3回印刷されます。

に置き換えるaa[:]、期待どおりの結果が得られます。

于 2012-10-05T15:30:11.037 に答える
1

カスタムクラスはここで役立ちます:

class Tester(object):
    "test object to reveal left to right evaluation"
    def __init__(self, value):
        self.value = value
    def __add__(self, value):
        print("adding ", value)
        return Tester(self.value + value)
    def __repr__(self):
        return repr(self.value)

実行時:

--> t = Tester(7)
--> t
7
--> t = t + 7
adding  7
--> t
14
--> def blah(a, b, c):
...   print(a, b, c)
... 
--> blah(t+1, t+2, t+3)
adding  1
adding  2
adding  3
15 16 17
于 2012-10-05T15:59:38.147 に答える
1

これは私見も示しています:

>>> '{} {} {}'.format(x,x+1,x+2)
'1 2 3'

編集:

>>> def f(t):   return time.time()-t 
...         

>>> t1=time.time(); '{:.4} {:.4} {:.4}'.format(f(t1),f(t1),f(t1))
'5.007e-06 7.868e-06 9.06e-06'
于 2012-10-05T15:46:07.670 に答える
0

短い答え:左から右

例:これは、算術演算を実行しているときに常に頭に浮かぶ質問であるため(floatに変換する必要があり、どの数値に変換する必要があるか)、その側面からの例を示します。

>>> a = 1/2/3/4/5/4/3
>>> a
0

整数を除算すると、当然のことながら、丸めが低くなります。

>>> a = 1/2/3/4/5/4/float(3)
>>> a
0.0

最後の整数をfloatに型キャストした場合でも、整数の除算のために数値がfloatで除算されるまでに、すでに0になっているため、ゼロになります。

>>> a = 1/2/3/float(4)/5/4/3
>>> a
0.0

上記と同じシナリオですが、フロート型キャストを少し左側にシフトします。

>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445

最後に、最初の整数をfloatに型キャストすると、結果は目的の整数になります。これは、最初の分割、つまり左端の分割から開始するため、floatを使用するためです。

補足1:算数評価を改善するためにそれに答えようとしている場合は、これを確認する必要があります

追加2:次のシナリオに注意してください。

>>> a = float(1/2/3/4/5/4/3)
>>> a
0.0
于 2014-11-19T18:54:49.000 に答える