【问题标题】:Print function calling functions together一起打印函数调用函数
【发布时间】:2018-12-29 07:15:00
【问题描述】:

我正在测试一些东西,我写这段代码是为了举例。我觉得我得到的输出很奇怪。我希望函数调用一个接一个地执行,但根据这段代码,两个打印语句都在之后执行彼此,然后将返回值一起打印。这是什么意思,这种情况下的代码流程是什么?

global num
num=5

def demo(num):
    num+=1
    print("hi")
    return(num)



print(demo(num),demo(num))

输出-

hi
hi
6 6

【问题讨论】:

  • @Patrick Haugh 这不是您标记的问题的副本。在这个问题中,这仅仅是因为最后一个 print 函数需要对其所有参数进行评估,然后才能输出任何内容,因此对 demo() 的两个调用都必须先完成,因此两个 his 都在数字之前打印.
  • @blhsing 函数调用是否从左到右计算?
  • 函数中的num 不是global num。它是同名的本地参数。您正在修改全局 num 的本地副本。要查看您想查看的内容,请从函数定义中删除形参并将global num 移动到函数定义中。
  • 您期待什么输出?我认为我已经猜到你的困惑在哪里,并写了一个答案来解释它,但我可能是错的。

标签: python python-3.x


【解决方案1】:

程序评估与算术一样具有操作顺序。同样,它并不总是直观的,尤其是当我们在阅读时从左到右、从上到下“消费”事物时。

那么,什么给了? 让我们成为 python 解释器,看看为什么操作顺序很重要。

# A wild statement appears. Time to compute!
print(demo(num),demo(num))
# I cant't print yet! i'm missing info! 

我需要先评估这个demo(num),默认情况下我会在远离全局变量的封闭房间内进行评估

# evaluating demo(num=5) - num here is a new local variable, it has no relation to the global one defined above
num+=1 # num = 6
print("hi") # [[[PRINT hi]]] ~> to console
return 6 # returns the value 6 filling in another piece of the puzzle

我们现在在哪里?差不多可以调用这个打印了,只需要再做这个演示的事情

print(6, demo(num))
# What is num though? 
# Well, the only num I know of out here in global space is 5
print(6, demo(5))
# evaluate: demo(5)

这似乎很熟悉!

# evaluating: demo(num=5) - again, a NEW local variable is created just for this function call
num+=1 # num = 6
print("hi") # [[[PRINT hi]]] ~> to console
return 6

最后,print 有了它需要的所有参数

print(6, 6) # [[[PRINT 6 6]]] ~> to console

print 不是魔法,它只是另一个功能! 和你写的demo 一样。

在提供所有参数之前,函数不会计算。

print(a, b) 需要 ab 的值才能执行其操作。

【讨论】:

  • 希望我有更多的时间来编辑并制作一个漂亮的树形图,用更少的文字来显示这个,但现在必须签字!希望这个“ELI5”版本对某人有所帮助。
【解决方案2】:

我希望函数调用一个接一个地执行

这正是发生的事情。

但是print 不可能发生在demo 调用之前,因为它试图打印出这些调用返回的值。 (你可以粗略地认为这是任何你看到括号的特殊情况:2 * (3+4) 不能乘以 2,直到它被添加 3+4,并且print(demo(num), demo(num)) 不能打印 demo(num) 的结果和demo(num) 直到它被称为它们。但不要从字面上理解它。)

所以,那些demo 调用从左到右发生,然后print 调用发生。


更详细地说,让我们逐步了解它如何评估这一行:

print(demo(num),demo(num))

…Python 必须这样做:

  • 通过将print 查找为内置名称来评估它,从而找到内置的print 函数。
  • 评估第一个参数。
    • 通过将demo 查找为全局名称来评估它,从而找到您定义的全局demo 函数。
    • 通过将 num 查找为全局名称来评估它,从而找到全局 5 值。
    • 在参数上调用函数。
    • 参数num获取传入的值5
    • num += 1将局部变量(参数为局部变量)num更新为6
    • print("hi") 打印出 hi
    • return(num) 返回局部变量 6 的值。
  • 评估第二个参数。
    • ……同上,打印出hi并返回6
  • 通过对两个调用返回的两个参数评估 print 来调用返回的函数,因此它会打印出 6 6

如果您想要严格的定义,他的详细信息在参考文档中的Calls 中进行了介绍。特别是(去除不相关的位)

call ::= primary "(" [argument_list] ")"

 …

主节点必须评估为可调用对象……。在尝试调用之前评估所有参数表达式。


根据这段代码,两个打印语句都在彼此之后执行,然后将返回值一起打印

是的。这两个函数调用必须按顺序执行,以便它可以获取要传递给print 函数的值。执行它们会打印出Hi 两次。然后它有所有的值,所以它可以print 它们,打印出6 6,因为这两个值都是6

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多