08 模块(Datawhale)

模块是一个包含所有自己定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用 Python 标准库的方法。知识来源于[1]

1. 什么是模块

容器 -> 数据的封装
函数 -> 语句的封装
类 -> 方法和属性的封装
模块 -> 程序文件

2. 命名空间

内置命名空间(Built-in Namespaces):Python 运行起来,它们就存在了。内置函数的命名空间都属于内置命名空间,所以,我们可以在任何程序中直接运行它们,比如id(),不需要做什么操作,拿过来就直接使用了。
全局命名空间(Module:Global Namespaces):每个模块创建它自己所拥有的全局命名空间,不同模块的全局命名空间彼此独立,不同模块中相同名称的命名空间,也会因为模块的不同而不相互干扰。
本地命名空间(Function & Class:Local Namespaces):模块中有函数或者类,每个函数或者类所定义的命名空间就是本地命名空间。如果函数返回了结果或者抛出异常,则本地命名空间也结束了。
程序在查询上述三种命名空间的时候,就按照从里到外的顺序,即:Local Namespaces --> Global Namesspaces --> Built-in Namesspaces

3. 导入模块

第一种:import 模块名
第二种:from 模块名 import 函数名 或者 from 模块名 import *(浪费所以不推荐)
第三种:import 模块名 as 新名字

4. if __name__ == '__main__'

Python 则不同,它属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口
if __name__ == '__main__'的意思是:当 .py 文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当 .py 文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。

关于__name__ == "__main__"的知识补充,来源于[2][3][4]

首先建立两个.py文件,前者是const.py,后者是area.py,对__name__ == "__main__"进行试验

PI = 3.14
def main():
    print("PI:", PI)
main()
# PI: 3.14
from const import PI
def calc_round_area(radius):
    return PI * (radius ** 2)
def main():
    print("round area: ", calc_round_area(2))
main()
# PI: 3.14
# round area:  12.56
  • 这里没有想通,不是只是import PI 吗?为什么会把之前的main也引入????

可以看到在两个.py中都设置了main函数,然后在第二个.py文件中先是引入了const包,再调用main的时候,把两个main都调用了
此刻修改前一个.py文件,加入if __name__ == "__main__":

# PI = 3.14
# def main():
#    print("PI:", PI)
# main()
# PI: 3.14

PI = 3.14
def main():
    print("PI:", PI)
if __name__ == "__main__":
    main()
# PI: 3.14

在加入if __name__ == "__main__":后运行const.py得到了原来一样的结果,说明if __name__ == "__main__":True
然后运行area.py,发现也不再调用const.pymain

from const import PI
def calc_round_area(radius):
    return PI * (radius ** 2)
def main():
    print("round area: ", calc_round_area(2))
main()
# 第一次
# PI: 3.14
# round area:  12.56

# 第二次
# round area:  12.56

所以if __name__ == "__main__":False
所以才有了下面的这句话:__name__是内置变量,可用于表示当前模块的名字。

import const
print(__name__)
# __main__
print(const.__name__)
# const

当在area.py中运行print(__name__),为__main__,也解释了之前的if __name__ == "__main__":True

area.py中,__name____main__area
area.py中,打const.__name__const

如果一个 .py 文件(模块)被直接运行时,其__name__值为__main__,即模块名为__main__

下面再进行一个小实验,建立一个module.py,验证上面所说的在area.py中,__name____main__area

def main():
  print "we are in %s"%__name__
if __name__ == '__main__':
  main()
# we are in __main__

如果是导入,这个和上面的print(const.__name__)类似

from module import main
main()
# we are in module

综上所述:
(1)“Make a script both importable and executable”
让你写的脚本模块既可以导入到别的模块中用,另外该模块自己也可执行。
(2)if __name__ == '__main__'的意思是:当 .py 文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当 .py 文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。
(3)__name__:是内置变量,可用于表示当前模块的名字。在自己的模块中,__name____main__是模块名字,print(__name__)是显示__main__,而在别的.py中引入const模块,是print(const.__name__)是显示const

(4)也就是说if __name__ == '__main__',当 .py 文件被直接运行时为真,缩进代码块将被运行;当 .py 文件以模块形式被导入时不为真,缩进代码块不被运行。
__name__:是内置变量,可用于表示当前模块的名字。在自己的模块中,print(__name__)是显示__main__,而在别的.py中引入再print(别的模块的名字.__name__)是显示别的模块的名字。注意结合(5)进行思考。

(5)之后我想了想,如果在第一个.py中不写上main,也就是

PI = 3.14
def main():
    print("PI:", PI)

运行后是什么都没有的
接着在第二个.pyrun

from const import PI
def calc_round_area(radius):
    return PI * (radius ** 2)
def main():
    print("round area: ", calc_round_area(2))
main()
# round area:  12.56

也就是如果说在第一个.py中不输入,在第二个的.py是没有效果的。

5. 搜索路径

当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入

6. 包

包是一种管理 Python 模块命名空间的形式,采用"点模块名称"。
创建包分为三个步骤:
(1)创建一个文件夹,用于存放相关的模块,文件夹的名字即包的名字。
(2)在文件夹中创建一个 __init__.py 的模块文件,内容可以为空。
(3)将相关的模块放入文件夹中。
在导入一个包的时候,Python 会根据 sys.path 中的目录来寻找这个包中包含的子目录。
目录只有包含一个叫做 __init__.py 的文件才会被认作是一个包,最简单的情况,放一个空的 __init__.py 就可以了。

[1]https://github.com/datawhalechina/team-learning-program/blob/master/PythonLanguage/15.%20%E6%A8%A1%E5%9D%97.md
[2]https://www.cnblogs.com/alan-babyblog/p/5147770.html
[3]https://www.jianshu.com/p/4b31e860287a
[4]https://blog.csdn.net/anshuai_aw1/article/details/82344884#1%20if%20__name__%20%3D%3D%20’%20rel=

你可能感兴趣的:(Python之禅)