读懂python代码_Python面试|一文让你读懂if __name__==’__main__’的含义

程序入口

对于很多编程语言来说,程序都必须要有一个入口,比如 C,C++,以及完全面向对象的编程语言 Java,C# 等。如果你接触过这些语言,对于程序入口这个概念应该很好理解,C 和 C++ 都需要有一个 main 函数来作为程序的入口,也就是程序的运行会从 main 函数开始。同样,Java 和 C# 必须要有一个包含 Main 方法的主类来作为程序入口。

而 Python 则有不同,它属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口。

一个 Python 源码文件除了可以被直接运行外,还可以作为模块(也就是库)被导入。不管是导入还是直接运行,最顶层的代码都会被运行(Python 用缩进来区分代码层次)。而实际上在导入的时候,有一部分代码我们是不希望被运行的。

举一个例子来说明一下,假设我们有一个 const.py 文件,内容如下:

PI = 3.14def main():

print "PI:", PI

main()

我们在这个文件里边定义了一些常量,然后又写了一个 main 函数来输出定义的常量,最后运行 main 函数就相当于对定义做一遍人工检查,看看值设置的都对不对。然后我们直接执行该文件(python const.py),输出:

PI: 3.14

现在,我们有一个 area.py 文件,用于计算圆的面积,该文件里边需要用到 const.py 文件中的 PI 变量,那么我们从 const.py 中把 PI 变量导入到 area.py 中:

from const import PIdef calc_round_area(radius):

return PI * (radius ** 2)def main():

print "round area: ", calc_round_area(2)

main()

运行 area.py,输出结果:

PI: 3.14round area: 12.56

可以看到,const 中的 main 函数也被运行了,实际上我们是不希望它被运行,提供 main 也只是为了对常量定义进行下测试。这时,if name== ‘ main‘ 就派上了用场。把 const.py 改一下:

PI = 3.14def main():

print "PI:", PIif __name__ == "__main__":

main()

然后再运行 area.py,输出如下:

round area: 12.56

再运行下 const.py,输出如下:

PI: 3.14

这才是我们想要的效果。

if name== ‘ main‘ 就相当于是 Python 模拟的程序入口。Python 本身并没有规定这么写,这只是一种编码习惯。由于模块之间相互引用,不同模块可能都有这样的定义,而入口程序只能有一个。到底哪个入口程序被选中,这取决于 name的值。

name

name是内置变量,用于表示当前模块的名字,同时还能反映一个包的结构。来举个例子,假设有如下一个包:

a├── b│ ├── c.py│ └── __init__.py└── __init__.py

目录中所有 py 文件的内容都为:

print(__name__)

我们执行 python -c “import a.b.c”,输出结果:

aa.ba.b.c

由此可见, name可以清晰的反映一个模块在包中的层次。其实,所谓模块名就是 import 时需要用到的名字,例如:

import tornadoimport tornado.web

这里的 tornado 和 tornado.web 就被称为模块的模块名。

如果一个模块被直接运行,则其没有包结构,其 name值为 main。例如在上例中,我们直接运行 c.py 文件(python a/b/c.py),输出结果如下:

__main__

所以,if name== ‘ main‘ 我们简单的理解就是: 如果模块是被直接运行的,则代码块被运行,如果模块是被导入的,则代码块不被运行。

实际上,这个问题还可以衍生出其他的一些知识点,例如 main.py 文件与 Python 的 -m 参数。

main.py 文件与 python -m

Python 的 -m 参数用于将一个模块或者包作为一个脚本运行,而 main.py 文件则相当于是一个包的”入口程序“。

首先我们需要来看看 python xxx.py 与 python -m xxx.py 的区别。两种运行 Python 程序的方式的不同点在于,一种是直接运行,一种是当做模块来运行。

先来看一个简单的例子,假设有一个 Python 文件 run.py,其内容如下:

import sys

print(sys.path)

我们用直接运行的方式启动(python run.py),输出结果(为了说明问题,输出结果只截取了重要部分,下同):

['/home/huoty/aboutme/pythonstudy/main', ...]

然后以模块的方式运行(python -m run.py):

['', ...]

/usr/bin/python: No module named run.py

由于输出结果只列出了关键的部分,应该很容易看出他们之间的差异。直接运行是把 run.py 文件所在的目录放到了 sys.path 属性中。以模块方式运行是把你输入命令的目录(也就是当前工作路径),放到了 sys.path 属性中。以模块方式运行还有一个不同的地方是,多出了一行 No module named run.py 的错误。实际上以模块方式运行时,Python 先对 run.py 执行一遍 import,所以 print sys.path 被成功执行,然后 Python 才尝试运行 run.py 模块,但是,在 path 变量中并没有 run.py 这个模块,所以报错。而正确的运行方式,应该是 python -m run.

这个例子并不能明显的说明问题。接着我们来看看 main.py 的作用。

仍然先看例子,有如下一个包:

package

├── __init__.py

└── __main__.py

init.pyimport sys

print("__init__")

print(sys.path)

main.pyimport sys

print("__main__")

print(sys.path)

用 python -m package 运行结果:

__init__

['', ...]

__main__

['', ...]

用 python package 运行结果:

__main__

['package', ...]

然后我们来总结一下:

1、 加上 -m 参数时会把当前工作目录添加到 sys.path 中,而不加时则会把脚本所在目录添加到 sys.path 中。

2、 加上 -m 参数时 Python 会先将模块或者包导入,然后再执行

3、 main.py 文件是一个包或者目录的入口程序。不管是用 python package 还是用 python -m package 运行时,main.py 文件总是被执行。

后序

我试图使用长篇大论来阐述,在 Python 中如何理解 if name== ‘ main‘ 这个问题,不知道我有没有描述得足够的明白。Python 的确是简单的,优雅的,但也有很多问题是不太容易理解的,例如很多高级的特性,像元类、生成器表达式、描述符、协程等。Python 并没有在太多的地方规定要如何如何,很多的用法只是惯用法,例如 self 和本文讨论的内容。这些用法或是为了让代码看起来更优雅,或是前人的经验。使用 Python 是有无限可能的,你可以写出很多简洁优雅的代码。

本文由 xyz蓝月 发布在 ITPUB,转载此文请保持文章完整性,并请附上文章来源(ITPUB)及本页链接。

原文链接:http://www.itpub.net/2019/06/13/2176/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543078.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言程序设计第三节课作业

1 指针是一个存储计算机内存地址的变量。从指针指向的内存读取数据称作指针的取值。指针可以指向某些具体类型的变量地址,例如int、long和double。指针也可以是void类型、NULL指针和未初始化指针。根据出现的位置不同,操作符 * 既可以用来声明一个指针变…

linux netcat测试udp端口,使用nc(netcat)测试udp协议与端口连通性

[v1.10]connect to somewhere: netcat [-options] hostname port[s] [ports] …listen for inbound: netcat -l -p port [-options] [hostname] [port]options:-g gateway source-routing hop point[s], up to 8-G num source-routing pointer: 4, 8, 12, …-h this cruft-i se…

Hession矩阵与牛顿迭代法

1、求解方程。 并不是所有的方程都有求根公式,或者求根公式很复杂,导致求解困难。利用牛顿法,可以迭代求解。 原理是利用泰勒公式,在x0处展开,且展开到一阶,即f(x) f(x0)(x-x0)f(x0) 求解方程f…

抽象工厂模式_设计模式——抽象工厂模式

阅读目录使用频率:★★★★★一、什么是抽象工厂模式二、补充说明三、角色四、例子使用频率:★★★★★一、什么是抽象工厂模式就是对一组具有相同主题的工厂进行封装(维基百科解释的很到位);例如:生产一台PC机,使用工…

Linux启动和退出系统的方法,实验二 Linux的启动与关闭

实验二 Linux的启动与关闭一、实验目的(1)掌握linux操作系统正确的启动与关闭方法;(2)理解系统运行级的概念,掌握查看和设置的方法;(3)理解系统运行级服务的概念,掌握查看、开启和关闭的方法;(4)理解LILO和GRUB的原理&…

linux需要什么基础,学linux需要什么基础?

近几年来,随着计算机网络的发展,越来越多的人学习 linux。对于想要从事运维工作或者从事智能开发方面的同学来说,学习 linux 是必要的。linux 的学习并不简单,那么这篇文章 w3cschool 小编来告诉你,学 linux 需要什么基…

python arima模型_Python时间序列处理之ARIMA模型的使用讲解

ARIMA模型ARIMA模型的全称是自回归移动平均模型,是用来预测时间序列的一种常用的统计模型,一般记作ARIMA(p,d,q)。ARIMA的适应情况ARIMA模型相对来说比较简单易用。在应用ARIMA模型时,要保证以下几点:时间序列数据是相对稳定的&am…

windows(win7,win8,xp)hosts文件找不到原因分析及解决方法

2019独角兽企业重金招聘Python工程师标准>>> 一般情况hosts文件是保存在C:\windows\System32\Drivers\Etc 文件夹上,由于安装是win7系统,在这个路径上就能找到这个hosts文件。如果你在该路径下没有找到这个文件的话,一般是以下几种…

linux虚拟化cpu的绑定,为虚拟机vCPU绑定物理CPU

使用taskset命令将vCPU线程绑定到指定的物理CPU。例如,某虚拟机的qemu进程及两个vCPU线程如下: ​[rootkelvin ~]# ps -eLo ruser,pid,ppid,lwp,psr,args | grep qemu | grep -v greproot 4706 3629 4706 1 qemu-system-x86_64 -m 2G -smp 2 /var/lib/li…

sql 显示百分比_轻松搞定数据分析之SQL——简单查询

每天早起或者睡前听一首温柔而美好的音乐,是一件很幸福的事情,无论你是否懂音乐,它都能带你发现生活中的隐藏的那些美好,今天我们先来一起欣赏Mindy Gledhill的单曲《California》California (网易云音乐),每次我听到这首歌&#…

SpringMVC 中设置日期字符串转换格式

2019独角兽企业重金招聘Python工程师标准>>> 在使用SpringMVC的项目中经常遇到 controller 参数中接收Date类型的数据,但是页面传过来的参数又是日期字符串,会出现转换异常。 由于项目需要支持两种日期格式所以从写了一个日期转换器。网友可以…

操作系统 非连续分配_操作系统中的连续和非连续内存分配

操作系统 非连续分配In this article, we will learn about the different types of memory management techniques and also the pros and cons of different memory management techniques. 在本文中,我们将学习不同类型的内存管理技术 ,以及不同内存管…

文件名重定向到txt中Linux,Linux上glob用于实现文件名的通配、IO重定向及管道

Linux中所谓的通配是指,显示以指定条件为条件的文件;即通配的含义是指搜寻以已知条件为前提的目标文件。常用文件通配符有:文件通配符含义例子*任意长度的任意字符如a*,搜寻所有以a为首的文件名的文件?任意的单一字符如a&#xff…

分形与数据结构第二篇

一、分形之 迭代实现分形 本次的图形都是在之前的画图工具中实现的。 首先,还是和原来一样建立一个JButton元素组件,然后加上监听方法;再在public void mouseClicked(MouseEvent e) {}方法中实现图形; else if (s.equals("图…

python socket 大文件_python之socket运用之传输大文件

socket建议最大的传输单元是8192个字符,但是如果超过8192就会出现问题,我们可以用下面的方法处理客户端代码import subprocessimport socketip_bind ("127.0.0.1",9000)client socket.socket()client.connect(ip_bind)l1 []while True:opti…

华为linux版笔记本安装win7,华为MateBook X Pro笔记本怎样安装win7系统

华为MateBook X Pro的制造工艺达到了业界顶级的水准,高达91%的屏占比真正达到了近似全面屏的观感,触感顺滑质感强烈的机身让人爱不释手。对于有意选购一台高端轻薄本产品的消费者来说,MateBook X Pro应该是你首选的对象之一。那么这款笔记本怎…

横竖屏切换

单一控制器的横竖屏切换 if ([[UIDevice currentDevice] respondsToSelector:selector(setOrientation:)]) { SEL selector NSSelectorFromString("setOrientation:"); NSInvocation *invocation [NSInvocation invocationWithMethodSignature:[UIDevice instanceM…

怎么使用小爱同学音响_智能音响购买指南!!!

小度音响pro100天使用感受,100天前我冲动消费购买了一个智能音响,还是对比了多个智能音响做好的决定。使用到现在显然这个冲动消费是非常划算的,这个智能音响完全提升了我的生活质量,我现在一下班就会让它播放音乐、睡觉前播放几段…

达芬奇linux 与win,抛弃Linux:达芬奇软件WIN版安装及设置.doc

达芬奇软件Windows版本安装及设置指南注意事项:1. windows帐户名一定要是英文,否则安装过程中解压临时文件路径中有中文,安装会出错。如果帐户名是中文,需要在环境变量里面将用户环境变量的路径设为英文路径2. 这里我的安装路径都…

今天的几件琐事

最近发现突然忙了一些之后,很多事情都给耽误了,暂且称为拖延症吧。原本计划的很不错的学习计划,最近貌似也给耽误了不少,虽然每天回来会想今天写点什么,今天忙了些什么,发现好像今天的进步不大。因为离自己…