Python 为什么没有 main 函数?为什么我不推荐写 main 函数?
毫无疑问 Python 中没有所谓的 main 入口函数,但是网上经常看到一些文章提“Python 的 main 函数”、“建议写 main 函数”……
有些人是知情的,他的意图可能是模仿那些正宗的 main 函数,但还有不少人明显是被误导了(或自己误解了),就写出来很累赘的代码。
本期“Python 为什么”栏目来聊聊 Python 为什么没有 main 函数?
在开始正题之前,先要来回答这两个问题:所谓的 “main 函数”是指什么?为什么有些编程语言需要强制写一个 main 函数?
某些编程语言以 main 函数作为程序的执行入口,例如 C/C++、C#、 Java、Go 和 Rust 等,它们具有特定的含义:
- main 函数名是强制的,也就是要求必须有一个 main 函数
- main 函数最多只能有一个,也就是说程序的入口是唯一的
- 语法格式有一定的要求,具有相对固定的模板
为什么要强制一个 main 入口函数呢?
这些语言是编译型语言,需要把代码编译成可执行的二进制文件,为了让操作系统/启动器找到程序的起点,所以要约定这一个函数。简单地说,就是在一大堆代码里,需要定义一个显著的可用于执行的开头。
不难看出,main 函数是那些语言中重要而不可缺的有机组成部分。
然而,我们再来看看 Python,情况就大不相同了。
- Python 是解释型语言,即脚本语言,运行过程是从上往下,逐行解析运行,也就是说它的起点是可知的
- 每个 .py 文件就是一个可执行文件,都可作为整个程序的入口文件,也就是说程序的入口是灵活可变的,没有必须遵守的约定
- 有时候运行 Python 项目,并没有指定入口文件(命令行中较常见,例如"python -m http.server 8000"), 那可能是存在
__main__.py
文件,它所在的包被当成一个“文件”来执行了
归结起来,意思是说 Python 这种脚本语言跟编译型语言不同,它不管是在单个模块层面(即一个 .py 文件),还是在由多个模块组成的包层面,都可选择灵活的执行方式,不像其它语言缺了约定好的入口就没法执行。
也就是说,Python 没有必要在语法层面规定程序员必须定义出一个统一的入口(不管是函数还是类还是什么东西)。
有些同学可能会有疑惑,因为他们经常看到或者自己写出下面这样的代码:
# main 里是某些主体代码
def main():
……
if __name__ == '__main__':
main()
难道这不就是 Python 的 main 函数么?相信有不少同学会这么想!
非也!非也!
除了函数名是“main”以外,它跟我们前面介绍的正统的 main 函数没有半毛钱关系,既没有强制性,也没有必然决定程序执行顺序的作用。缺少它,也不会导致什么语法问题。
之所以有些知情人要命名出一个”main“函数,其实是想强调它的”主要“地位,想要人为地安排它作为第一个执行的函数。他们可能认为这样命名的函数,比较容易记忆。
之所以有些知情人要写if __name__ == '__main__'
,可能想表明 main() 只有在当前脚本被直接执行时才运行,不希望被导入其它模块时运行。
对于这些“知情人”,他们有一定的道理。
但是,我个人并不推荐这种写法,甚至有时候会非常反感!
最明显的例子:明明只有几十行代码,或者仅有一个脚本文件,实现一个简单的功能(一小段爬虫、用 turtle 画张图等等),但是它们都按前面的样式写了。
我每次看到这种不假思索的累赘代码,就觉得难受。为什么要写那行 if 语句呢?可能的话,应该拆分 main 函数,甚至不必封装成一个函数啊!
我个人总结出以下的经验:
- 打破惯性思维,写出地道的代码。main 入口函数是某些语言特有的,不该在 Python 中“照猫画虎”,应该了解脚本语言的特点,写出简洁优雅的风格
- 使用 main.py 而非 main()。因为 Python 的程序执行单位其实是脚本文件,而非某个函数或者类,所以建议把入口文件命名为 main.py,内部的函数按需求而定
- 可以的话,使用
__main__.py
作为入口文件。这个文件结合命令行的“-m”参数使用,非常好用。推荐阅读:Python 中 -m 的典型用法、原理解析与发展演变 - 不推荐写
if __name__ == '__main__'
。首先,如果只有一个文件的话,因为不存在导出的可能,不建议写。其次,存在多文件时,入口文件(main.py)中极不推荐写这一句,此文件的代码逻辑应该精炼,理论上其内容不该被导出到其它模块使用,因为它是起点!最后,多文件的非入口文件也不建议写,因为在非入口文件中写这个判断,最大的作用就是写一些测试代码,但是测试代码应该分离出来,写到专门的目录或文件中。
小结:本文首先解释了什么是 main 入口函数,以及为什么某些语言会强制要求写 main 函数;接着,解释了为什么 Python 不需要写 main 函数;最后则是针对某些人存在的惯性误区,分享了我个人的四点编程经验。
本文属于“Python为什么”系列文章(Python猫出品),该系列主要关注 Python 的语法、设计和发展等话题,以一个个“为什么”式的问题为切入点,试着展现 Python 的迷人魅力。部分话题会推出视频版,请在 B 站收看,观看地址:视频地址
公众号【Python猫】, 本号连载优质的系列文章,有Python为什么系列、喵星哲学猫系列、Python进阶系列、好书推荐系列、技术写作、优质英文推荐与翻译等等,欢迎关注哦。
Python 为什么没有 main 函数?为什么我不推荐写 main 函数?的更多相关文章
- MathType怎么写分段函数?
分段函数是数学里面特有的一种函数,它是对于自变量x的不同的取值范围,有着不同的解析式的函数.它的特点就是有一个大括号,然后有至少2个函数解析式,写这样的函数离不开专业的公式编辑器,下面就来学习具体编辑 ...
- Python学习札记(二十) 函数式编程1 介绍 高阶函数介绍
参考: 函数式编程 高阶函数 Note A.函数式编程(Functional Programming)介绍 1.函数是Python内建支持的一种封装,我们通过一层一层的函数调用把复杂任务分解成简单的任 ...
- 计算机基础,Python - 回调函数,使用装饰器注册回调函数
1. 参考: https://en.wikipedia.org/wiki/Callback_(computer_programming) https://developer.mozilla.org/e ...
- 【C++实现python字符串函数库】二:字符串匹配函数startswith与endswith
[C++实现python字符串函数库]字符串匹配函数startswith与endswith 这两个函数用于匹配字符串的开头或末尾,判断是否包含另一个字符串,它们返回bool值.startswith() ...
- 【C解毒】怎样写main()函数
[C解毒]怎样写main()函数(出处: CUNIX论坛)
- 为什么c程序里一定要写main函数
一. 学习过程 编写程序f.c: 对其进行编译,正常通过,再对其进行连接,出现错误: 显示的出错信息为: 翻译成中文是:在c0s模块没有定义符号’_main’. 那么这个错误信息可能与文件c0s.ob ...
- python函数(6):内置函数和匿名函数
我们学了这么多关于函数的知识基本都是自己定义自己使用,那么我们之前用的一些函数并不是我们自己定义的比如说print(),len(),type()等等,它们是哪来的呢? 一.内置函数 由python内部 ...
- Python学习日记day10------函数的命名空间、作用域与闭合函数
1,参数陷阱 如果默认参数的只是一个可变数据类型,那么每一次调用的时候,如果不传值就共用这个数据类型的资源. 2,三元运算 c=a if a>b else b#如果a>b返回a,否则,返回 ...
- Python函数的定义、参数传入与函数的调用
作为计算机代码的一种抽象方式,函数在Python中扮演了极为重要的角色.今天给大家介绍Python函数的定义.参数的传入以及调用方式.其中函数参数的传入方式为本节重点内容.Python函数的参数形式包 ...
随机推荐
- java基础篇 之 异常丢失
我们看如下代码: @Slf4j public class Test { public static void main(String[] args) { try { try { test(); } f ...
- 微信小程序下拉刷新时有部分区域不随着下拉移动
问题 区域元素使用(position: fixed),小程序页面下拉刷新时,这部分区域不会随页面下拉移动. 如何解决 删除设置的top属性
- search(12)- elastic4s-聚合=桶+度量
这篇我们介绍一下ES的聚合功能(aggregation).聚合是把索引数据可视化处理成可读有用数据的主要工具.聚合由bucket桶和metrics度量两部分组成. 所谓bucket就是SQL的GROU ...
- html5 canvas 绘制上下浮动的字体
绘制上下浮动的字体主要思想为先绘制好需要的字体,每隔一定的时间将画布清空,然后再将字体位置改变再绘制上去 如此循环即可. (function(window) { var flowLogo = func ...
- C# 数据操作系列 - 10 NHibernate初试
0. 前言 在上一篇基本讲完了EF Core的入门级教程.从这一篇开始,我们试着去探索一下 .net core平台上更多的ORM框架.那么,这一篇开始我们就来试试NHibernate. 1. NHib ...
- webpack指南(一)HRM+Tree Shaking
参考:https://www.cnblogs.com/PasserByOne/p/12084323.html https://blog.csdn.net/qq593249106/article/det ...
- SpringBoot注解分析
Spring boot 简介:是spring社区发布的一个开源项目,旨在帮助开发者更快更简单的构建项目,使用习惯优于配置,的理念让你的项目快速的跑起来,使用springboot可以不用,或者很少的配置 ...
- P4525 【模板】自适应辛普森法1
P4525 [模板]自适应辛普森法1 #include <bits/stdc++.h> using namespace std; ; double a, b, c, d, l, r; in ...
- 14.4 Go Xorm
14.4 Go Xorm 获取xorm go get -u -v github.com/go-xorm/xorm xorm增删改查 /** * 应用程序 * 同目录下多文件引用的问题解决方法: * h ...
- DPDK开发环境搭建(学会了步骤适合各版本)
一.版本的选择 首先要说明的是,对于生产来说DPDK版本不是越高越好,如何选择合适的版本? 1.要选择长期支持的版本LTS(Long Term Support) 2.根据当前开发的系统环境选择 可以在 ...