关于Python中__main__的概念性查询

时间:2012-06-29 19:22:04

标签: python function main conceptual

我目前正在使用Python,并且对__main__中列出的函数感到困惑。我一直在查看多个python脚本,试图找到一个共同主题,关于哪些函数在__main__中保证一个位置,但无济于事。在这里,我有一个自己的代码示例。 firstfunctionanotherfunction是我的代码中唯一的两个函数。

def main(argv):

    firstinput=""
    secondinput=""

    if len(argv) < 3 or len(argv) > 3:
        print """"Please set to:
                metisfinal.main(metisfinal.py, firstinput, secondinput)""""
        return
    else:
        firstinput = argv[1]
        secondinput = argv[2]

    firstfunction(firstinput, dictionary)
    anotherfunction(list, secondinput)

if __name__ == "__main__":
    main(sys.argv)

(我认为)我知道参数和__main__调用是正确的,但firstfunctionanotherfunction总是返回错误(因为它们的参数不是全局定义的)。我很肯定这是因为对__main__的错误理解而产生的,因为我所看到的所有其他例子,基本上都是以相同的方式设置__main__

什么构成列出__main__中的特定功能?我偶然发现了一些Python代码,其中包含超过30个函数,但程序员只在__main__中列出了其中2个函数。同样,有时代码会在主参数中有类,就像这一个(Project之前被定义为对象类):

def main(argv):

    filename = ""
    outputfilename = ""

    p = Project(filename, outputfilename, subdomainNames) 
    p.generateICs()

if __name__ == "__main__":
    main(sys.argv)

从概念上讲,我无法理解为什么没有列出所有函数...难道不是所有函数都需要运行或__main__只是初始化某些东西吗?

我在看非典型代码吗?我错过了__main__的哪些关键概念?一旦我确实找到了要放入__main__的函数,是否有一种特定的格式化方法?

2 个答案:

答案 0 :(得分:8)

__main__”中列出的含义并不清楚。 __main__不是源文件中的实体。相反,它是模块的名称,如果直接执行它。当您执行if __name__=="__main__"时,您告诉Python执行该块中的代码,当且仅当代码作为主模块执行时 - 即,如果它是正在运行的程序。如果从其他模块导入模块,则不会运行if __name__=="__main__"块中的代码。

请注意,如果阻止,则不会“列出”该功能。相反,您将常规程序代码放在要运行的块中。通常这段代码只调用一个函数。人们经常称这个函数为main()。但__main__main之间没有特殊关系。您可以随意调用该功能:

def snicklefritz():
    # This function will be run when you run the program
    print "You ran the program!"

if __name__ == "__main__":
    snicklefritz()

尝试运行此程序(例如,将其保存为“snicklefritz.py”,然后从命令行执行python snicklefritz.py)。你会看到“你运行了程序!”打印。如果您创建了一个import snicklefritz的单独文件,则不会打印该消息。

请注意,“列表功能”没有任何内容。例如,看看这个程序:

print "This will always be printed!"

if __name__ == "__main__":
    print "This will only be printed if you run the file as a program!"

这里if __name__=="__main__"块没有“列出”任何函数。它只包含当文件作为脚本运行时运行的实际代码。但是,人们通常不会这样做,因为将代码放在一个单独的函数中而不是仅仅在函数外部“暴露”它更为整洁。

对于其他功能,您可以在模块中定义您喜欢的任何其他功能,在该模块中使用,或者由导入模块的其他模块使用。通常,模块中的大多数函数不会在if __name__=="__main__"块中使用,因为它们不会成为“main”函数的一部分。相反,它们将是其他代码使用的其他功能。例如:

def otherFunc(x):
    # Return x squared
    return x**2

def snicklefritz():
    # This function will be run when you run the program
    print "You ran the program!"

if __name__ == "__main__":
    snicklefritz()
模块中根本没有使用

otherFunc。没关系。可能有人想要导入您的模块并自己使用otherFunc。并非每个函数都必须在同一个模块中使用,更不用说从if __name__=="__main__"块调用了。

答案 1 :(得分:3)

你误解了__main__成语。

考虑以下程序,保存在名为sum.py的文件中:

def read_numbers():
    n1 = int(raw_input())
    n2 = int(raw_input())
    return n1, n2

def sum_numbers(i1, i2):
    return i1+i2

def print_sum(i1, i2, i3):
    print "%d + %d = %d" % (i1, i2, i3)

v1, v2 = read_numbers()
sum = sum_numbers(v1, v2)
print_sum(v1, v2, sum)

它有三个功能 - 一个从标准输入读取两个数字,另一个对它们求和,第三个打印操作。在定义函数之后,我以这样的方式调用它们,即我们读取两个数字并打印它的总和。相当容易。如果我执行它,我得到这样的东西:

$ python sum.py 
12
34
12 + 34 = 46

现在,假设我需要编写另一个只能读取一个数字的程序 - 实际上是另一个数字。由于我已经拥有sum_numbers()函数和print_sum()函数,因此我很想重复使用sum模块,这是一件好事:

import sum
MY_FIXED_NUMBER=3
n = int(raw_input())
value = sum.sum_numbers(n, MY_FIXED_NUMBER)
print_sum(n, MY_FIXED_NUMBER, value)

大!但是,如果我执行它,我得到了什么?这样:

$ python three_sum.py 
12
34
12 + 34 = 46
12
12 + 3 = 15

WAT?程序问我两个数字,打印它们的总和,然后要求第三个数字,正确地总结为3.我只是想要被要求第三个数字,并且只打印3个数字!发生了什么?

当我导入模块(例如import sum)时,它的所有代码都被执行了。所以,我的模块有两个部分,一个定义了可以在别处使用的有用函数(我将其称为定义部分),以及它以某种方式执行此函数的部分结果,所以我可以将模块用作程序(我将其称为执行部分)。执行部分总是被执行。

幸运的是,Python有一个技巧,只有当模块导入时才允许我执行执行部分。如果我导入带有import的Python文件,模块将有一个名为__name__的变量,其名称将是模块的原始名称:

>>> import sum
12
34
12 + 34 = 46
>>> sum.__name__
'sum'

但是,如果我将Python文件作为脚本运行($ python sum.py),__name__变量将存在,但名称不同。假设我添加了一行,例如

print __name__

sum.py的末尾。当我再次运行时,我明白了:

$ python sum.py
12
34
12 + 34 = 46
__main__

另一方面,如果我运行three_sum.py,则print __name__的结果会有所不同:

$ python three_sum.py 
12
34
12 + 34 = 46
sum
12
12 + 3 = 15

是的,将文件作为脚本运行时__name__变量的值为__main__

那么,这对我有什么帮助?这样:我将把我的模块的执行部分放在if条件下。如果模块的名称是__main__,那是因为文件作为带有$ python sum.py的脚本运行 - 在这种情况下,我应该执行模块的执行部分。所以我的sum.py模块现在就是这样的:

def read_numbers():
    n1 = int(raw_input())
    n2 = int(raw_input())
    return n1, n2

def sum_numbers(i1, i2):
    return i1+i2

def print_sum(i1, i2, i3):
    print "%d + %d = %d" % (i1, i2, i3)

if __name__ == "__main__":
    v1, v2 = read_numbers()
    sum = sum_numbers(v1, v2)
    print_sum(v1, v2, sum)

如果我运行$ python sum.py,我会像以前一样:

$ python sum.py
12
34
12 + 34 = 46

但是,如果我运行three_sum.py,则一切都不同:

$ python three_sum.py 
12
12 + 3 = 15

现在这可以按预期工作了。它的工作方式是这样的,因为第一次执行中的模块名称是__main__,因此执行if __name__ == "__main__"下的命令。但是,在第二次执行中,模块的名称为sum,因此if下的命令不会执行。

即使你的文件设计为导入,将文件的执行部分放在if __name__ == "__main__"下仍然是一个好习惯,所以你的文件很容易适应成为一个模块。