调用print语句中的函数的Python顺序?

时间:2017-08-06 22:49:45

标签: python

我们说我有

def foo(n):
    print("foo",n)

def bar(n):
    print("bar",n)

print("Hello",foo(1),bar(1))

我希望输出为:

Hello
foo 1 None
bar 1 None

但相反,我得到的东西让我感到惊讶:

foo 1
bar 1
Hello None None

为什么Python在打印" Hello"之前首先调用函数?打印" Hello",然后调用foo(1),让它打印输出,然后打印"无"作为它的返回类型。然后调用bar(1)并打印该输出,并打印"无"作为它的返回类型。 Python(或其他语言)是否有理由以这种方式调用函数,而不是按照它们出现的顺序执行每个参数?

编辑:现在,我的后续问题是内部发生了什么,如果从左到右评估表达式,Python会以某种方式临时存储每个参数的返回值?例如,现在我理解它将从左到右评估每个表达式,但最后一行表示Hello None None,因此Python以某种方式记住每个函数的执行,第二个参数和第三个参数的返回值为{ {1}}?例如,在评估None时,它会打印foo(),然后点击不返回语句,那么它是否存储在foo 1没有返回值的内存中?

4 个答案:

答案 0 :(得分:3)

引用documentation

  

Python从左到右评估表达式。请注意,在评估作业时,右侧会在左侧之前进行评估。

大胆强调我的。因此,首先评估所有表达式,然后将其传递给print

观察打印电话的字节代码:

  1           0 LOAD_NAME                0 (print)
              3 LOAD_CONST               0 ('Hello')
              6 LOAD_NAME                1 (foo)
              9 LOAD_CONST               1 (1)
             12 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             15 LOAD_NAME                2 (bar)
             18 LOAD_CONST               1 (1)
             21 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             24 CALL_FUNCTION            3 (3 positional, 0 keyword pair)
             27 RETURN_VALUE
首先调用

fooLINE 12)和barLINE 21),然后调用printLINE 24 - 3个位置args)

关于存储这些中间计算值的位置的问题,那就是call stackprint只需将它们从堆栈中弹出即可访问返回值。 <子> - Christian Dean

答案 1 :(得分:3)

正如documentation

中指定的那样
  

Python 从左到右评估表达式。请注意,在评估分配时,右侧会在左侧之前进行评估。

这意味着如果你写:

print("Hello",foo(1),bar(1))

相当于:

arg1 = "Hello"
arg2 = foo(1)
arg3 = bar(1)
print(arg1,arg2,arg3)

因此在函数调用之前评估参数。

当我们有一棵树时也会发生这种情况:

def foo(*x):
    print(x)
    return x

print(foo(foo('a'),foo('b')),foo(foo('c'),foo('d')))

打印为:

>>> print(foo(foo('a'),foo('b')),foo(foo('c'),foo('d')))
('a',)
('b',)
(('a',), ('b',))
('c',)
('d',)
(('c',), ('d',))
(('a',), ('b',)) (('c',), ('d',))

因为Python因此从左到右评估参数。它将首先评估foo(foo('a'),foo('b')),但为了评估foo(foo('a'),foo('b')),首先需要评估foo('a'),然后评估foo('b')。然后,所有foo(foo('a'),foo('b'))都可以使用之前调用的结果。

然后它想要评估第二个参数foo(foo('c'),foo('d'))。但为了做到这一点,它首先评估foo('c')foo('d')。接下来,它可以评估foo(foo('c'),foo('d')),然后最终可以评估最终表达式:print(foo(foo('a'),foo('b')),foo(foo('c'),foo('d')))

所以评估等同于:

arg11 = foo('a')
arg12 = foo('b')
arg1 = foo(arg11,arg12)
arg21 = foo('c')
arg22 = foo('d')
arg2 = foo(arg11,arg12)
print(arg1,arg2)

答案 2 :(得分:2)

在评估所有参数之前,不会调用封闭函数。这与数学的基本规则一致,即括号内的操作在外部操作之前执行。因此print() {em}

答案 3 :(得分:1)

答案很简单: 在python中,像print这样的函数的参数总是首先从左到右进行求值。

看看这个stackoverflow问题:In which order is an if statement evaluated in Python

None只是函数的返回值。它首先执行函数,然后打印其返回值