一、模块(Module)

1、模块的作用

一个Python模块其实就是一个脚本文件,具有后缀“.py”,例如 hello.py 就是一个模块文件名,和普通文件一样可以被永久保存在本地存储磁盘中。



2、模块的内容

     Python模块中存放的是一些程序代码,例如,变量定义、函数定义或是代码语句。下面是hello.py模块的内容,其中有一个变量 a,一个函数 fun(),和一个打印语句。

# -*- coding:UTF-8 -*-
#! /usr/bin/python3
a = [1, 2, 3]
def fun():
        return 'fun()'
print('hello', fun(), a)

     这里介绍一个模块属性 __name__ ,该属性存储了当前模块的名称,比如,上面的 hello.py 其__name__就是 'hello.py'



3、模块的使用

     (1)第一种方式时将模块当做脚本执行,模块中的代码语句会得到执行

wuhui@wuhui-H55M-S2H:~/Desktop$ python3 hello.py
hello fun() [1, 2, 3]

     (2)第二种方式时将模块导入,然后使用导入模块中定义的变量、函数等

>>> import hello
>>> hello.a
[1, 2, 3]
>>> hello.fun()
'fun()'

     使用"import module"导入模块方式时,被导入模块不能带后缀;使用导入模块中定义的变量、函数时,必须使用模块名作为前缀,如"hello.a"而不是直接使用"a"。如果感觉这样麻烦的,可以使用下面的方式,将模块中所有的定义信息全部导入。

>>> from hello import *
>>> a
[1, 2, 3]
>>> fun()
'fun()'



4、模块的相关信息

     每个模块都有自己的定义信息,包括变量、函数等以及一些“与生俱来”的内建变量,这些可以通过Python内建函数 dir() 来查看。

直接在终端下输出dir(),输出当前环境下的变量名

>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

导入上面的 hello.py 模块后,使用dir()查看,不仅输出了默认的的变量名,还输出了hello.py中我定义的变量a和函数fun的名称

>>> import hello
>>> dir(hello)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'fun']

输出模块名

>>> print(hello.__name__) 
 
 hello


5、模块的搜索路径

     当导入模块时,Python按照一定的搜索顺序在指定的目录下搜索模块,如果找到则导入模块,否则会引发异常。例如,执行 “import hello”导入hello.py模块时,Python解释器首先根据模块名搜索内建模块;如果没有找到,则会去 sys.path 变量所列出的目录下搜索,sys.path的默认目录如下:

     (1)输入脚本所在目录(或当前目录,如果没有指定导入脚本,如 import ×)

     (2)环境变量 PYTHONPATH 所指定的目录(这个与系统环境变量中的PATH语法相同)

     (3)安装的目录(默认)

    如果导入的脚本是一个符号连接(Windows上的快捷方式),搜索目录是符号链接所连接的原始文件所在目录,而非符号连接所在目录。在Python解释器初始化之后,可以在程序中修改 sys.path


二、包(Package)

1、包的作用

     简言之,包就是一个容器,用来存放其他的模块和包。

     如果你之前接触过其他语言,相信包的概念应该不会陌生,其作用和 C++/C#中的namespace相似,与java中的包相似。Python中提出包的概念是为了方便不同模块的组织。当一个项目较大时,编写的模块数量众多而且是由不同成员编写的,这时候就难免会出现模块名、变量名、函数名、类名等重名的情况,虽然可以在名称前加前缀来区分,但这种 做法始终不是很好,没有将模块的组织结构体现出来。使用包组织模块,就可以通过 "A.B"的方式来引用模块,其结构类似与树状,很清楚。下面是一个包的结构:

PkgA/                         # 顶层包
    __init__.py               # 初始化 PkgA
    PkgB/                     # PkgA 的子包 PkgB
        __init__.py           # 初始化 PkgB
        module1.py
        module2.py
    PkgC/                     # PkgA 的子包 PkgC
    __init__.py               # 初始化 PkgC
        module1.py
        module2.py

    在包PkgA下面出现了同名的模块 module1.py和 module2.py ,通过添加子包 PkgB和 PkgC将其区分。


2、包的使用 —— 导入模块、变量、函数、类

     PkgB 下面的 module1.py 文件内容如下:

def say():
        print(’hello')

    现在如果需要使用 PkgB下module1.py中定义的函数 say(),可以采用下列方式(导入变量、类方法一样):

# 方式一:导入函数所在模块
>>> import PkgA.PkgB.module1
>>> PkgA.PkgB.module1.say()
hello
# 方式二:从包 PkgA.PkgB 中导入函数所在模块
>>> from PkgA.PkgB import module1
>>> module1.say()
hello
# 方式三:从模块中导入函数
>>> from PkgA.PkgB.module1 import say
>>> say()
hello

     注意:使用 “import item” 导入时,“item”必须是一个包或模块,并且如果要引用item中定义的变量、函数或类,需要加上“item”这一前缀。

     方式一,比较繁琐;方式三,容易产生同名;推荐使用方式二。如果导入的模块中没有同名的函数 say() ,那么使用方式三会简洁许多。但是如果导入的模块或当前文件中已经定义了say,而你又需要使用模块module1中的函数say()那么就只能使用方式二了,通过前缀区分,例如下面代码:

>>> from PkgA.PkgB import module1
>>> module1.say()
hello
>>> def say():
...     print('world')
...
>>> say()
world
>>> module1.say()
hello


3、包的相关信息

     包下面有一个名为 "__init__.py" 的文件,存在该文件时,Python会将目录当做一个包来看待(不过好像没有也行,这里尚不清楚,知道的请留言补充). __init__.py 为一个空文件时没什么问题的, 不过__init__.py 里面也可以存放初始化代码和变量 __all__。当导入当前包下面的模块或其他包时,首先当前包中的__init__.py 中的可执行代码会被执行,紧接着导入的模块中的可执行代码也会被执行。由于包或模块只会被导入一次(即使再次使用import导入也无效果),因此这些可执行代码只会被执行一次。

"import package import *"时,只导入变量__all__中的定义的模块,而其他模块则不会被导入,这样可以防止"import *"的将所有模块导入导致加载缓慢和命名空间的污染。拿前面的代码举个例子:

# __init__.py中未定义__all__时
from PkgA.PkgB import *     # 仅仅导入包 PkgB
# __init__.py 中定义 __all__ = ['module1']
from PkgA.PkgB import *     # 只导入PkgB包中的模块 module1,而模块 module2则不会被导入

4、包的相对路径

     导入包时出了使用绝对路径,如 "from PkgA.PkgB import module1" 外,还可以使用相对路径,"."表示当前包,“..”表示上一级包。拿前面的代码举个例子,如果想在 PkgA.PkgC.module1中使用 PkgA.PkgB.module2中的函数 say(),可以这么写:

from ..PkgB from module2          # 这里的"..PkgB"就相当于"PkgA.PkgB"

4. 包的搜索路径

     当导入包时,Python会在sys.path 指定的目录下搜索,前面提到的sys.path默认目录如下,你也可以在程序中修改sys.path的值。

     (1)输入脚本所在目录(或当前目录,如果没有指定导入脚本,如 import ×)

     (2)环境变量 PYTHONPATH 所指定的目录(这个与系统环境变量中的PATH语法相同)

     (3)安装的目录(默认)