什么是模块(Module)
在计算机程序的开发过程中,随着程序代码越写越多,写在一个文件里的代码就会越来越长,越来越不容易维护。
为了让代码方便维护,我们将代码进行分类,分别放到不同的文件里。这样,所有的代码都按照一定的规则分布在各个文件里,需要使用的时候只要导入相应的文件即可。在 Python 中,这样的文件被称之为模块(Module)。
在我们的教学环境中,其实我们每次运行代码,都是在运行一个名为 main.py 的程序文件,相当于我们在命令行中执行 python main.py 去运行 main.py 里的代码。
在我们的教学环境中,除了默认的 main.py 外,我们还可以点击右边的 + 来添加新的文件。像这样,每一个单独的 .py 文件,本质上都是一个模块。
和函数一样,模块也能提高代码复用率。就像我们把多次用到的代码块封装成函数一样,我们可以把经常用到的函数、变量等代码封装成一个模块,在需要的时候导入这个模块。
Python 提前帮我们把一些常用的函数和变量写到了内置模块中,比如数学计算中常用的开根号方法——math.sqrt()
方法,圆周率 π 的数值——math.pi
等。关于内置模块的更多知识我们下一关会学到。
最后我们来总结一下模块的作用:
导入模块
当我们需要使用模块的时候,只需使用 import
语句导入对应的模块即可。我们来看一个例子,这个例子中有两个模块,一个是 other.py 文件,另一个是 main.py 文件。
# other.py
print('带你打开编程世界的大门')# main.py
import other # 导入 other 模块
# 输出:带你打开编程世界的大门
我们使用 import 模块名
(不需要 .py 后缀)导入模块,相当于我们在 main.py 里借用并运行了 other.py 文件里的代码,因此运行结果是 带你打开编程世界的大门。你可以理解为 Python 会将 import other
语句替换成 other.py 里的代码。
其实在执行 import other
后,import other
被替换成 other.py 里的代码,main.py 里的代码就相当于下面这样:
print('hi')
print('带你打开编程世界的大门')
print('bye')
上面的代码是为了让你理解 import
的作用,其实一般模块里的代码大都是定义好的变量和函数等。我们再来看一个例子:
# other.py
pi = 3.14159265359def half(x):return x / 2# main.py
import other # 导入 other 模块print(other.pi)
# 输出:3.14159265359print(other.half(4))
# 输出:2.0
我们可以看到,当导入模块后,要使用模块中的变量、函数,需要通过 模块名.变量名
和 模块名.函数名()
的方式。.
表明了从属关系,表示某个模块里面的某个变量或函数。
import
语句还有一种用法是 import ... as ...
,比如我们觉得 other 这个模块名太长,就可以用 import other as o
,相当于给 other 取了一个别名为 o
,之后我们就可以使用 o
来替代 other
。
导入部分模块
import
语句一次性将整个模块导入进来,我们还可以使用 from ... import ...
语句只导入我们需要的变量、函数等。举个例子:
# other.py
pi = 3.14159265359def half(x):return x / 2# main.py
from other import pi, half # 从 other 模块导入 pi 和 halfprint(pi)
# 输出:3.14159265359print(half(4))
# 输出:2.0
可以看到,执行 from other import pi, half
后可以直接使用 other.py 里的 pi 和 half,不再需要在前面加 other.
。并且同时导入多个变量或函数时,两两之间要用逗号隔开。
需要注意的是:使用 from ... import ...
的方式导入就不能再用 模块名.变量名
和 模块名.函数名
的方式访问模块内的变量或函数了,否则代码将会报错:
# other.py
pi = 3.14159265359def half(x):return x / 2# main.py
from other import pi, halfprint(pi)
# 输出:3.14159265359print(other.half(4))
# 报错:NameError: name 'other' is not defined on line 6
最后我们来总结一下 from ... import ...
语句:
程序入口
当在做复杂项目的时候,我们会将代码拆分到各个模块中。这样,我们就需要一个程序入口,通过这个入口文件将整个项目的代码串联运行起来。
程序入口,指的就是你 直接运行 的那个 .py
文件。举个例子,main.py
中导入了其他的模块 other.py
,接着,我们将 main.py
直接运行,这时 main.py
就是作为程序入口直接运行的,而 other.py
则是以导入的形式运行的。
程序入口的功能,是指明模块中某一段代码在何时才会被运行。如果想让 代码块 B 仅在 abc.py
作为程序入口时才能运行,那就可以在代码中这样写:
# abc.py
代码块 Aif __name__ == '__main__':代码块 B
上面代码的意思是当 __name__ 的值为 '__main__' 时执行 代码块 B,那这里的 __name__ 和 '__main__' 又都是什么呢?请听我慢慢道来:
__name__ 这个东西看起来很奇怪,但它的本质其实就是一个 变量。它是 Python 里一个特殊的内置变量,默认值是 模块名。
但当模块作为程序入口时,__name__ 的值会被改为 '__main__',总结对比一下:
如果 abc.py 以导入的方式被运行,那 abc.py 中的 __name__ 值就是 'abc';
如果 abc.py 被直接运行,那 abc.py 中 __name__ 的值会被改为 '__main__'。
注意:__name__ 和 '__main__' 前后都是两个下划线哦~
所以我们可以根据 __name__ 的这个特性来判断模块是以导入的方式使用,还是作为程序入口文件直接运行,从而执行相对应的操作。比如只有作为程序入口执行时才运行启动程序的代码,否则什么都不做。
def bootstrap():print('项目启动')if __name__ == '__main__':bootstrap()
上面这段代码只有在作为程序入口直接运行时才会自动执行 bootstrap()
,打印出 项目启动。
我们来看个例子加深一下理解。main.py
和 other.py
的内容如下,先不要看结果,根据上面的讲解猜猜看,直接运行 main.py
时会打印出什么。
# other.py
print('我是 other 模块')if __name__ == '__main__':print('other 模块被直接运行了')# main.py
import otherprint('我是 main 模块')if __name__ == '__main__':print('main 模块被直接运行了')
先不要看答案,先想想会输出什么呢??
代码输出如下,你猜对了吗?
我是 other 模块
我是 main 模块
main 模块被直接运行了
跟着我来逐行理解一下吧。我们直接运行了 main.py
,第一行代码 import other
导入了 other.py
模块。
other.py
是以导入的方式被运行的,它并不是程序入口,所以,print('other 模块被直接运行了')
这行代码不会执行。屏幕上只会打印出 我是 other 模块。
导入 other.py
后,接下来就是运行 main.py
中的代码啦。main.py
是程序入口,所以 print('main 模块被直接运行了')
这句代码会被执行。屏幕上逐行打印出 我是 main 模块 和 main 模块被直接运行了 这两句话。
现在是不是清晰很多了呢?如果还有哪里不明白,可以再回顾一下前面的讲解,好好理解一下哦~
本章练习题:
鸡兔同笼
鸡兔同笼问题是《孙子算经》中的经典题目,也是小学奥数题里的常客。
原书中是这么描述的:“今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?”
翻译成现代汉语就是:“鸡和兔放在一个笼子里,笼子里共有 35 个头,94 个爪,那鸡和兔各有多少只?”
请你根据下面的要求,用 Python 来完成这道数学题,和它一起“奥数”:
- 在
solution.py
中建立函数calculate()
,该函数能算出鸡和兔分别的数量;- 在主程序
main.py
中导入函数calculate()
,根据题干中的“总头数”和“总脚数”输出问题的答案。
# main.py
# 请补全代码,导入 solution 模块
from solution import calculate
# 下面是老师写好的目标输出格式,请不要更改哦
# 多返回值函数返回的是【元组】,字符串格式化输出中,% 后跟的也是【元组】
#
print('笼中有兔%d只,有鸡%d只' % calculate(35, 94))# solution.py
def calculate(head,foot):# 总数量不等于35# for i in range(head):# 假设i是兔,j是鸡,那么总头数 - 兔数 = 鸡数# j = head - i# 如果4 * 兔数 + 2 * 鸡数 = 总足数# if 4*i + 2*j == foot:# return i,j# 方法二# 循环兔子数量for i in range(1,35):# 循环鸡的数量for j in range(1,35):if j * 2 + i * 4 == 94 and i + j == 35:return i,j# 输出结果为:「笼中有兔12只,有鸡23只」