【问题标题】:"Boilerplate" code in Python?Python中的“样板”代码?
【发布时间】:2025-12-24 08:40:06
【问题描述】:

Google 有一个 Python 教程,他们将样板代码描述为“不幸”并提供了以下示例:

#!/usr/bin/python

# import modules used here -- sys is a very standard one
import sys

# Gather our code in a main() function
def main():
  print 'Hello there', sys.argv[1]
  # Command line args are in sys.argv[1], sys.argv[2] ..
  # sys.argv[0] is the script name itself and can be ignored

# Standard boilerplate to call the main() function to begin
# the program.
if __name__ == '__main__':
  main()

现在,我听说样板代码被描述为“为了获得看起来应该更简单的结果而一次又一次出现的看似重复的代码”(example)。

无论如何,在 Python 中,上面示例中被视为“样板”代码的部分是:

if __name__ == '__main__':
  main()

现在,我的问题如下:

1) Python 中的样板代码(如提供的示例)是否采用与我提供的定义相同的定义?如果有,为什么?

2) 这段代码是否必要?在我看来,无论是否有 main 方法,代码都会运行。是什么让使用此代码更好?是不是更好?

3) 我们为什么使用该代码以及它提供什么服务?

4) 这会在整个 Python 中发生吗?还有其他“样板代码”的例子吗?

哦,还有一个题外话:你需要import sys 才能在 Python 中使用命令行参数吗?如果它不存在,它如何处理这样的论点?

【问题讨论】:

  • sys 无论您是否导入它都存在。如果你不这样做,你就不能在你的代码中使用它。
  • 只是对此特定样板代码的评论,您应该始终使用#!/usr/bin/env python 而不是!#/usr/bin/python,因为这会获取用户/环境特定的python 版本。这是可取的,因为用户可以将 python 称为其他东西或安装在 /bin 以外的位置,尽管通常这些东西都不正确。然而,作为一个处理过由此产生的错误的人,我可以告诉你,他们非常令人沮丧。这有点像硬编码路径或使用相对路径之间的区别。
  • 例如 Python 2 和 3 的样板,看看python-boilerplate.com
  • 一个重要的用途是所有从main() 运行的函数和类都被提升。这自然会在 nodejs 等语言中发生,如果用户希望 main() 位于调用下面其他函数的脚本顶部,这将非常有用。

标签: python boilerplate


【解决方案1】:

我同样对教程中的“样板代码”的含义感到困惑:这是否意味着可以在简单的脚本中避免使用此代码?还是对强制使用这种语法的 Python 特性的批评?甚至是使用此“样板”代码的邀请?

我不知道,但是,经过多年的 Python 编程,我至少清楚了不同语法的作用,即使我可能仍然不确定什么是最好的方法。

您通常希望将测试或要执行的代码放在脚本代码的末尾,但这有一些影响/副作用:

  1. 即使脚本被导入,代码也会被执行,这很少是我们想要的。
  2. 代码中的变量和值在调用命名空间中定义和导出
  3. 脚本末尾的代码可以通过调用脚本 (python script.py) 或从 ipython shell (%run script.py) 运行来执行,但无法从其他脚本运行。

避免在所有条件下执行以下代码的最基本机制是语法:

if __name__ == '__main__':

这使得代码只有在脚本被调用或运行时才运行,避免了问题1。其他两点仍然成立。

带有单独main() 函数的“样板”代码添加了进一步的步骤,不包括上述第 2 点和第 3 点,因此例如,您可以从不同的脚本调用多个测试,有时可以采取另一个级别(例如:多个函数,每个测试一个,因此可以从外部单独调用它们,以及一个调用所有测试函数的 main,而无需从外部知道它们是哪一个。

我补充说,我发现这种结构通常不令人满意的主要原因,除了它的复杂性之外,有时我想保留第 2 点,但如果将代码移动到单独的函数,我就会失去这种可能性。

【讨论】:

    【解决方案2】:

    您不需要为不打算成为更大项目一部分的一次性脚本添加if __name__ == '__main__'。请参阅here 以获得很好的解释。仅当您想单独运行文件并将其作为模块与其他 python 文件一起包含时才需要它。

    如果你只想运行一个文件,你可以有零样板:

    print 1
    

    并使用$ python your_file.py 运行它

    Adding the shebang line #!/usr/bin/python 和运行 chmod +x print_one.py 让你能够运行

    ./print_one.py

    最后,# coding: utf-8 允许您将 unicode 添加到您的文件中,如果您想将❤ 放在任何地方。

    【讨论】:

      【解决方案3】:

      让我们花点时间看看你打电话给import sys时发生了什么:

      • Python 查看列表并引入 sys 模块
      • 它找到argv 函数并运行它

      那么,这里发生了什么?

      在其他地方编写的函数正在用于执行当前程序范围内的某些操作。以这种方式编程有很多好处。它将逻辑与实际劳动分开。

      现在,就样板而言,有两个部分:

      • 程序本身(逻辑),在main 下定义,以及
      • 检查main是否存在的调用部分

      您实际上是在main 下编写程序,使用您在定义main(或其他地方)之前定义的所有函数,并让Python 查找main

      【讨论】:

        【解决方案4】:

        1) 主要样板很常见,但不能再简单了

        2) main() 在没有样板文件的情况下不会被调用

        3) 样板允许将模块用作独立脚本,作为其他程序中的库

        4) 这很常见。 doctest 是另一个。

        训练成为 Python 大师……祝你论文好运! ;-)

        【讨论】:

          【解决方案5】:

          在这种情况下,if __name__ == "__main__": 块被称为样板的原因是它复制了许多其他语言中自动执行的功能。在 Java 或 C++ 等许多其他语言中,当您运行代码时,它会查找 main() 方法并运行它,甚至会抱怨它不存在。 Python 运行文件中的任何代码,因此您需要告诉它运行main() 方法;一个简单的替代方法是将运行 main() 方法作为默认功能。

          所以,if __name__ == "__main__": 是一种可以更短的常见模式。没有理由你不能做一些不同的事情,比如:

          if __name__ == "__main__":
            print "Hello, Stack Overflow!"
          
            for i in range(3):
              print i
          
            exit(0)
          

          这会很好用;虽然我的例子有点傻,但是你可以看到你可以放任何你喜欢的东西。 Python 设计者选择了这种行为而不是自动运行main() 方法(可能不存在),大概是因为 Python 是一种“脚本”语言;因此您可以将一些命令直接写入文件,运行它,然后执行您的命令。我个人更喜欢 Python 的方式,因为它使初学者更容易在 Python 中启动,而且拥有一门 Hello World 是一行的语言总是很不错的。

          【讨论】:

          • 我见过一些直接运行测试的模块,有时我自己也使用相同的方法。确保您在开发过程中不会破坏某些东西非常方便。当然,当作为模块导入时,测试不会运行。
          【解决方案6】:

          您使用“if main”检查的原因是,您可以让模块在顶层运行其代码的某些部分(以创建事物——常量、函数或类——它导出),并且只运行某些部分当作为脚本执行时(例如对其功能进行单元测试)。

          后一个代码应该包装在一个函数中的原因是因为main()块的局部变量会泄漏到模块的范围内。

          现在,另一种设计可能是,作为脚本执行的文件必须声明一个名为 __main__() 的函数,但这意味着在语言中添加一个新的魔法函数名称,而 __name__机制已经存在。 (并且无法删除,因为每个模块都必须有一个__name__,并且作为脚本执行的模块必须有一个“特殊”名称,因为模块名称是如何分配的。)引入两种机制来做同样的事情仅仅为了摆脱两行样板——通常是两行样板每个应用程序——似乎并不值得。

          【讨论】:

            【解决方案7】:
            1. 它是重复的,因为它对您可能从命令行执行的每个脚本都重复。
            2. 如果您将主代码放在这样的函数中,您可以导入模块而不执行它。这有时很有用。它还使事情更有条理。
            3. 据我所知与 #2 相同
            4. Python 通常非常擅长避免样板。它足够灵活,在大多数情况下,您可以编写代码来生成样板代码,而不是编写样板代码。

            题外话:

            如果您不编写代码来检查参数,它们将被忽略。

            【讨论】: