资讯专栏INFORMATION COLUMN

python基础教程:Python模块(module)

whinc / 3694人阅读

摘要:如果你这个脚本想要使用其它脚本里面的变量函数和类也是可以的,在你这个脚本里面用来导入要引用的脚本,而那个被引用的脚本就称作模块。

在此之前,我们运行一些简短的Python代码,都是通过Python解释器(python或ipython)进行的,如果我们退出解释器再重新运行解释器后,上次敲进去的变量、函数等都不见了,没有保存下来。为了保存我们曾经写过的代码,就是要写成.py文件,称为脚本

如果你这个脚本想要使用其它脚本里面的变量、函数和类也是可以的,在你这个脚本里面用import来导入要引用的脚本,而那个被引用的脚本就称作模块(module)

简单来说,一个Python源码文件(*.py)就是一个模块。

我们的第一个Python模块

接下来,我们用文本编辑器(比如,前面介绍的VS Code)来创建一个名为 my_first_module.py的文件作为我们编写的第一个模块:

#!/usr/bin/env python3
# coding:utf-8
# Author: veelion
# file name: my_first_module.py

"""My First Module"""

MY_NAME = "My_First_Module"

def my_print(a):
    print(MY_NAME, " print", a)

def my_add(a, b):
    return a+b

我们的第一个Python模块里面有一个全局变量:MY_NAME,两个函数:my_print()my_add()。接着我们在这个文件所在目录运行Python解释器ipython:

In [1]: import my_first_module

In [2]: my_first_module?
Type:        module
String form: 
File:        ~/p2/tutorial/md_Python/codes/my_first_module.py
Docstring:   My First Module

In [3]: my_first_module.MY_NAME
Out[3]: "My_First_Module"

In [4]: my_first_module.my_add(2, 3)
Out[4]: 5

In [5]: my_first_module.my_print("猿人学")
My_First_Module  print 猿人学

导入模块用import,模块名称就是文件名my_first_module.py去掉文件后缀.py后的名字。从上面ipython的使用中,我们可以看到模块中的函数、变量都是可以被拿来用的。

注意: Python模块的文件名只能是字母、数字和下划线,不能有-,+等其它符号,否则导入会报错,原因很简单,比如-符号会和Python里面的减号混淆。

把上面的模块重命名为my-first-module.py,再import导入一下看看:

In [6]: import my-first-module
  File "", line 1
    import my-first-module
             ^
SyntaxError: invalid syntax
Python模块的二三事

(1)模块可以包含可执行的全局语句。这些语句应该是用于初始化该模块,它们只在第一次被import时执行。我们来举个例子,创建两个只包含一句print的模块:

# m1.py
print("m1 is imported")
# m2.py
import m1
print("m2 is imported")

main.py中导入m1m2这两个模块:

import m1
import m2
import m1

print("I am main.py")

这里m1被显性导入两次,还有一次被m2阴性导入,一共导入三次,那么是不是m1 is imported会被打印3次呢?我们运行这个脚本试试看: python main.py。猜猜运行结果是怎样的?

m1 is imported
m2 is imported
I am main.py

结果是只被打印了一次。这就是只在第一次被import时执行的意思。再试试把main.py中的两个import m1都去掉,只import m2会是什么结果?

(2)每个模块都都它自己私有的符号表,它被当做全局符号表被该模块中所有函数使用,也就是说,每个模块都有自己的名字空间。因此,模块里面可以尽情(如有必要)使用全局变量,而不用担心它们与模块使用者的全局变量冲突。用户使用模块中的全局变量也很简单:modname.itemname
比如,my_first_module模块中的MY_NAME使用时就是my_first_module.MY_NAME,而在你自己的脚本里面同样可以命名MY_NAME的全局变量,而不会和my_first_module里面的冲突。

(3)模块可以import其它模块。模块导入语句import不一定要在脚本的最开始,可以在代码其它位置需要时导入。当然,在最开始导入是最清晰、规范的做法。

import 模块的各种方式

我们使用import的方式很多,前面那种 import module_name的方式是最常用的,也是代码规范推崇的用法。从语法上讲还有其它方式:

(1)用from导入部分:

In [1]: from my_first_module import my_add

In [2]: my_add(1,3)
Out[2]: 4

In [3]: my_print("hi")
---------------------------------------------------------------------------
NameError         Traceback (most recent call last)
 in 
----> 1 my_print("hi")

NameError: name "my_print" is not defined

In [4]: my_first_module.my_add(1,2)
---------------------------------------------------------------------------
NameError         Traceback (most recent call last)
 in 
----> 1 my_first_module.my_add(1,2)

NameError: name "my_first_module" is not defined

通过from modname import xxx的方式,我们只导入了my_add,调用my_print就会出错。并且,my_first_module模块名称也是未定义的,即没有被导入。

(2)用from导入部分并重命名
跟(1)一样,只不过把导入的名称起了别名而已,使用时用别名:

from my_first_module import my_add as myadd

(3)用from导入全部

In [1]: from my_first_module import *

In [2]: my_add(1,2)
Out[2]: 3

In [3]: my_print("猿人学")
My_First_Module  print 猿人学

In [4]: MY_NAME
Out[4]: "My_First_Module"

这种方式看似简单,写代码时省去了模块名称my_first_module这个前缀。但是,这个省略带来很大隐患,会限制我们自己命名。如果我们自己命名和模块里面的名称一样,就会覆盖模块里面的名字。

这种import的方式是代码规范严禁杜绝的

(4)重命名模块
如果模块名称很长,我们可以给它起个短一点的别名,这样写代码会简单些:

In [1]: import my_first_module as mfm

In [2]: mfm.my_add(1,2)
Out[2]: 3

In [3]: mfm.my_print("猿人学")
My_First_Module  print 猿人学

In [4]: mfm.MY_NAME
Out[4]: "My_First_Module"

这个和import my_first_module实际上一样,只是使用的名称变为mfm。模块的别名可以任意起,只要和其它名称区分开来就好。

(5)模块重新加载
我们写完一个模块,可能要通过Python解释器(如ipython)进行验证一下,于是运行Python解释器,import模块,发现模块的某个函数有错误,就在编辑器修改了该函数并保存该模块文件。继续在刚才打开的解释器里面验证那个有错误的函数,发现刚才的修改没生效,竟然没有生效!!!

为什么呢?为了效率,每个解释器导入的模块只导入一次。因此,如果你中途修改了模块,就要出解释器重新进入并重新导入模块才能使修改生效。如果不退出解释器而重新导入模块,不管你运行多少次import modname都是无效的,因为解释器一看这个模块已经导入过了,就不费劲再导入一次了。解释器懒,你就不能懒。

或者,可以不重新启动解释器而使用importlib.reload()重新导入。

把Python模块当做脚本运行

任何Python文件都可以这样来运行:

python3 file.py

一个文件的Python模块当然也可以这样运行。一个Python文件,前面是函数的定义,定义完要运行,我们就要写调用语句,最初你相到的可能是这样的:

# Author: veelion
# file: mylib.py

def add(a, b):
    return a+b

print(add(2, 3))

通过python mylib.py运行一下,就可以得到运行结果。

目前看起来一切正常,你看看有没有问题?

回头看看上面模块二三事的第(1)条,如果这个文件当做模块被其它文件import时,是不是也会运行打印语句?这条打印语句往往是我们为了验证add()函数而进行的,属于测试阶段的代码,而交付给他人作为模块使用时,它是不需要的。那么,该怎么办?

通过__name__属性就可以来限制print(add(2, 3))语句的运行。文件作为脚本运行时,它的__name__属性是__main__,而作为模块被import时,它的__name__属性是模块的名称。

先看看模块被import时的__name__

In [24]: import mylib
5

In [25]: mylib.__name__
Out[25]: "mylib"

我们可以看到,import mylib后打印出了5,也就是运行了print(add(2, 3))语句。

然后,我们修改mylib.py文件,把测试语句修改一下:

# Author: veelion
# file: mylib.py

def add(a, b):
    return a+b

if __name__ == "__main__":
    print(add(2, 3))

再次在ipython解释器里面导入该模块时就不会打印出5,也就是那句print不再执行。
而在命令行下运行python3 mylib.py这个脚本就会执行那句print语句,因为这种执行方式下,模块的__name____main__

这些用__name__ == "__main__"条件判断的代码通常是该模块的测试代码,或者是如何使用该模块的示例代码。

Python模块总结

(1)一个Python文件就是一个模块;
(2)一个模块可以import其它模块;
(3)在Python解释器运行中,一个模块只可以被import一次,除非使用importlib.reload();
(4)模块中的可执行语句(非函数、类的定义)仅在该模块被import时执行一次。
(5)import模块的方式有多种,要使用最规范的方式。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43800.html

相关文章

  • python基础教程模块高级技巧

    摘要:标准模块附带了一个标准模块库。它返回一个如果调用不传递参数,则列出当前已经定义的所有名字用可以查看所有的内置类型变量函数等,方法是借助标准模块模块高级技巧总结的搜索路径,顺序一定要搞得清编译后的文件内置函数查看模块定义的名字。 上一节,我们讲解了Python模块的基础知识,这一节我们继续深入了解模块的更多知识,从而让大家全面了解、掌握和运用模块到我们实际的编程中。 在上一节中有一句话接...

    JasinYip 评论0 收藏0
  • Python基础教程第二版》第五章-条件、循环和其他语句(一)

    摘要:所解包的序列中的元素数量必须和赋值符号左边的变量数量完全一致。其中,冒号标识语句块开始块中每一个语句都是缩进相同量退回到和已经闭合的块一样的缩进量时,表示当前块结束。成员资格运算符字符串和序列比较字符串可按照字母顺序比较。 print和import print打印多个表达式,用逗号,隔开 print abc:, 42, nonono #输出在每个参数之间添加空格 print在结尾处加上...

    宋华 评论0 收藏0
  • python基础教程:包,对,没错,绝对不是双肩包!

    摘要:比如,模块名表示包中名为的子模块。例如,文件可以包含以下代码定义了之后,就会把,,导入到当前命名空间。这种导入使用前导点来指示相对导入中涉及的当前包和父包。也就是说被执行的主程序里面不能包含相对导入。 包,Package,是一种Python模块的集合,从文件组织形式上看,包就是一个文件夹,里面放着各种模块(.py文件),也可以有子文件夹(子包)。包名构建了一个Python模块的命名空间...

    wuyangnju 评论0 收藏0
  • 「Odoo 基础教程系列」第一篇——环境准备

    摘要:安装好后,在中执行查看版本信息,应该会看到输出如下信息版本号可能会不同如果提示未找到,则需要手动将用户基础目录下的添加到中。相关文章基础教程系列第篇开天坑啦 showImg(https://segmentfault.com/img/bV4GZu?w=1262&h=911); 之前说好的 「Odoo 基础教程系列」终于来了(撒花)~刚过完年重新投入到工作中,一下子事情有点多都要忙不过来了...

    szysky 评论0 收藏0

发表评论

0条评论

whinc

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<