Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何证明参数评估为;“从左到右”;用Python?_Python_Parameter Passing_Operator Precedence - Fatal编程技术网

如何证明参数评估为;“从左到右”;用Python?

如何证明参数评估为;“从左到右”;用Python?,python,parameter-passing,operator-precedence,Python,Parameter Passing,Operator Precedence,例如,在JavaScript中,我们可以编写如下程序: var a=1; testFunction(++a,++a,a); 函数testFunction(x,y,z){ document.writeln(“x=“+x”); document.writeln(“y=“+y”); document.writeln(“z=“+z”); } 我们将得到一个输出: x = 2 y = 3 z = 3 这意味着在JavaScript中参数是从左到右进行计算的。在C语言中,我们将得到输出 x = 3 y

例如,在JavaScript中,我们可以编写如下程序:

var a=1;
testFunction(++a,++a,a);
函数testFunction(x,y,z){
document.writeln(“
x=“+x”); document.writeln(“
y=“+y”); document.writeln(“
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)

Python不允许我在调用函数参数时在函数参数内执行任何新赋值(例如
f(x=4,x,x)
或类似的内容)。

反汇编函数调用

>>> 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        
使用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]
,相同的最终对象被打印三次


如果我们将
a
替换为
a[:]
,我们将得到预期的结果。

这也显示了它的含义:

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


自定义类可以在此处提供帮助:

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

简短回答:从左到右

例如: 由于这是一个在我做算术运算时经常出现在我脑海中的问题(我是否应该转换为浮点数,以及转换为哪个数字),因此给出了一个这方面的示例:

>>> 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
与上面的场景相同,但将float类型转换稍微移向左侧

>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445
最后,当我们将第一个整数类型转换为浮点时,结果就是所需的结果,因为从第一个除法开始,即最左边的除法,我们使用浮点

额外的1:如果你试图回答这个问题以改进算术评估,你应该检查一下

额外2:请注意以下情况:

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

哇,这是一个很酷的答案,但更像是困惑。这是参数的一般评估顺序吗?不能说这是有效的。你有什么要进口的吗?我得到
name错误:没有定义名称“dis”
我没有忘记导入它。。。O.OWell我会得到这个
回溯(最近一次调用最后一次):文件“”,第1行,在dis.dis(foo)name错误:当我键入dis.dis(foo)时,没有定义名称“dis”。不知道为什么。即使过了一点就可以理解了?尽管如此,还是欢迎您的解释…@Geo Papas:remmember在Python 2中,
print
不是函数调用。因此,请使用Python3 print()函数。这个示例是Python2,请检查是否使用Python3得到相同的结果(您肯定会得到)。很抱歉,它不起作用,我想Python3中有一个变化。我得到了输出
None[1,2,3]None[1,2,3]None[1,2,3]
@AnujGupta+1非常好的答案,我会接受这一点,但larsmans有一个更简单、更有趣的例子。嗯,我不能接受两个答案吗oThis在Python 2下工作,如果您首先使用来自uuu future uuuuu import print_u函数的
+1,很好的回答实际上,在C中,您会得到UB(因此输出可能会因环境而异)。实际上“这意味着参数在JavaScript中是从左到右进行计算的。”–否,这意味着,对于这个特定环境中的这个特定实现的这个特定版本,在这个特定代码的特定运行中,参数的求值方式是从左到右的。例如,它没有提到在不同的CPU上的不同操作系统上运行的不同实现。您展示的代码在C语言中有未定义的行为,这意味着实现可以做任何它想做的事情。它可以打印
11 7 5
,它可以打印
4
,它可以什么都不打印,它可以格式化你的硬盘。所有这些都是规范允许的。这个例子没有任何东西表明
x+2
x
之前没有被评估过。简短而简单——非常好。
>>> a = 1/2/3/float(4)/5/4/3
>>> a
0.0
>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445
>>> a = float(1/2/3/4/5/4/3)
>>> a
0.0