Python中的执行顺序和编码风格

时间:2010-06-06 17:09:08

标签: python

我是Python的新手,所以如果问题太基础,请不要激怒我。)

我已经读过Python从上到下执行。

如果是这种情况,为什么程序会这样:

def func2(): 
    pass

def func1():
    func2()

def func():
    func1()

if __name__ == '__main__':
    func()

所以从我所看到的,主要功能最后,其他功能堆叠在它上面。

我说错了吗?如果不是,为什么主函数或函数定义不是从上到下编写的?

编辑:我在问为什么我不能这样做:

if __name__ == '__main__':
    func()

def func1():
    func2()

这不是自然顺序吗?你继续在底部添加东西,因为它是从上到下执行的。

9 个答案:

答案 0 :(得分:28)

def只是创建功能。除了解析语法并将函数绑定到这些名称之外,不执行任何代码。

if是实际执行代码的第一位。如果你把它放在第一位,并在定义之前调用一个函数,结果是一个NameError。因此,您需要在定义函数后将其放置。

请注意,这与PHP或JavaScript不同,其中函数被“提升” - 任何函数定义都会在其他所有内容之前进行处理和解析。在PHP和JavaScript中,完成您所说的内容并在源代码中定义函数比调用它们的位置完全合法。 (JS中的一个细节是,像function(){}这样定义的函数被提升,而像var func1=function(){};这样定义的函数则没有。我不知道它如何与PHP 5.3中的匿名函数一起工作。

请参阅此处cat()将正确打印,yip()会为您提供NameError,因为解析器在您调用它时未获得yip()的定义。

def cat():
  print 'meowin, yo'

cat()

yip()

def yip():
  print 'barkin, yall'
  喵喵,哟喔   追溯(最近的呼叫最后):
   文件“cat.py”,第5行,在      叶先生()
  NameError:名称'yip'未定义

答案 1 :(得分:20)

Python从上到下执行,但执行“def”块不会立即执行包含的代码。相反,它在当前范围中创建具有给定名称的函数对象。考虑一个Python文件,就像你的例子一样:

def func2():
    print "func2"

def func1():
    func2()

def func():
    func1()

if __name__ == '__main__':
    func()

执行此脚本时会发生以下情况:

首先,创建一个函数对象并将其绑定到全局范围中的名称“func2”。然后创建一个函数对象并将其绑定到全局范围中的名称“func1”。然后一个叫做“func”。然后执行“if”语句,条件为真并执行“func()”语句。此时,“func”是在全局范围内找到的函数对象,因此调用它并运行其代码。该代码包含“func1()”语句,该语句被解析为对“func1”函数的调用,依此类推。

如果你把“if”语句放在顶部,那么当它执行时,还没有任何用名称“func”定义的东西,所以你会得到一个错误。要认识到的重要一点是“def”语句本身就是一个执行的语句。它与其他语言不同,其中定义是一种单独的声明,没有执行顺序。

另请注意,只要“if __name__ ...”位在文件的末尾,其他声明的顺序并不重要,因为到时候它们中的任何一个被称为所有“def”已被执行。

答案 2 :(得分:4)

Python通常会从上到下处理命令。但是,函数调用将导致Python执行该函数,并且仅在该调用结束后继续向下。

在您的示例中,Python解释器执行以下步骤:

  1. 定义func2
  2. 定义func1
  3. 定义func
  4. 处理if语句if __name__ == '__main__':
  5. 调用func函数(因为条件为真)。
  6. 调用func1函数(因为这是func的作用)。
  7. 调用func2函数(因为这是func1的作用)。
  8. 结束,因为在完成对func2的调用之后,它还调用了func1,因此调用了func,这是代码中的最后一个语句。

答案 3 :(得分:2)

if __name__ == "__main__"部分结尾,因为无论你的主要功能是什么,都需要脚本中的所有其他定义。如果在主块中有任何其他功能定义 ,那么就不可能在那里使用它们,因为那时解释器还没有看到它们。

答案 4 :(得分:1)

def语句只是定义一个函数 - 它们实际上不会在调用函数之前运行它。因此,为什么他们通常会在任何代码使用它们之前出现 - 他们将该功能设置为将来使用。

def语句并不是硬性要求,将__main__代码放在最底层是非常常见的(除其他外,它清楚地说明了该部分中的内容以及内容不是,因为if以下的任何内容都是该部分的一部分)。它还确保您要从该部分调用的任何内容已经def'd。

答案 5 :(得分:1)

对于你的问题的第二部分(Python中的编码风格),我将看看PEP 8,它提供了由Guido van Rossum(BFDL本人!)编写的风格指南,并提供了基础知识编写Pythonic代码。

答案 6 :(得分:0)

确实,惯例是将“main”函数放在文件末尾的“if __name__ == '__main__'”语句之上。我认为这是因为我们通常希望功能靠近他们的呼叫站点。

对于调用函数上方的被调用函数,我认为这只是重构的结果。至少在我的情况下,我倾向于编写一个函数,然后取出一些代码放入子函数中,我把它放在顶部以便我能看得更清楚。

这只是代码组织的一种原始形式。如果有一个更强大的内聚单元,我很想把这些功能放到他们自己的模块中。

答案 7 :(得分:0)

还值得注意的是,只要不执行函数调用,就可以在“定义它们之前”进行调用。在此提及此错误,因为它是常见的Python新错误。其他示例都没有显示这种“以一种方式还可以”的行为。 (虽然不是真的推荐)

def hi():
  pie()

#hi() cannot be called here, doesn't work because hi depends on pie

def pie():
  print('hi pie')

hi() # it's ok to call here!

您甚至可以走得更远(这个例子有点愚蠢,但我相信它阐明了这个例子)

runIt = False
def hi():
  if runIt:
    pie()

hi() #now ok, as the code won't call pie.
runIt = True
#hi() #wouldn't be ok as now the code will call pie.

def pie():
  print('hi pie')

hi() # ok here too!

答案 8 :(得分:0)

您需要了解两点:

  1. main条件是在以下情况下阻止运行阻止代码 该模块已导入。在我们的情况下,条件为真,因为 我们的文件未导入。
  2. 代码工作如下:
    • 定义func2
    • 定义func1
    • 定义func
    • 处理if语句if __name__ == '__main__' :(在我们的示例中为 True
    • 调用func函数
    • 致电func1
    • 调用func2函数
    • 返回结果(打印消息func2
    • 结束