1

模块与包

1. 模块

在 python 中一个 .py,文件就是一个模块,模块名就是文件名不要后缀,导入模块就可以引入模块中已经写好的功能,这样做的好处就是,后期维护起来更方便,程序结构更加清晰,python中模块可以分为 python内置模块第三放模块自定义模块

1.1 导入模块

导入模块的方式有很多

import 模块名: 使用时需要带上模块名,声明是使用该模块的名称
from 模块名 import 功能名: 使用时不需要带上模块名,容易与当前名称空间中的名字起冲突,当前名称空间存在相同的名字,则后定义的名字会覆盖之前定义的名字
from 模块名 import *: 表示将当前模块名所有的名字都导入到当前位置,不推荐
from 模块名 import 功能名 as 别名: 导入的名字过长时采用起别名来 精简代码 另外为被导入的名字起别名也可以很好的 避免与当前名字发生冲突,可以保 证调用方式的一致性

导入内置模块

import math
print(math.sqrt(9))  # 3.0

导入自定义模块
foo.py

x=1  
def get(): 
    print(x) 
    
def change():  
    global x x=0  
    
class Foo:  
    def func(self): 
    print('from the func')
在另一个文件引入这个模块,会执行原文件代码,产生一个新的名称空间用于存放源文件执行过程中产生的名字,当前执行文件所在的名称空间得到一个名字foo,该名字指向新创建的的模块和名称空间,若要引用模块名称空间中的名字,需要加上前缀
# 导入模块foo 
import foo 

# 引用模块foo中变量x的值赋值给当前名称空间中的名字a 
a=foo.x 

# 调用模块foo的get函数 
foo.get() 

# 调用模块foo中的change函数 
foo.change() 

# 使用模块foo的类Foo来实例化,进一步可以执行obj.func()
obj=foo.Foo() 
加上 foo. 作为前缀就相当于说明要引用 foo 名称空间中的名字,所以肯定不会与当前执行文件所在名称空间中的名字相冲突

1.2 导入模块顺序

  • python内置模块
  • 第三方模块
  • 自定义模块

1.3 __all__

如果一个模块文件中有__all__变量,当使用from xxx import *导入时,只能导入这个列表中的元素。

my_module模块代码

__all__ = ['func']


def func():
    print('func')


def bar():
    print('bar')

导入模块的文件代码

from my_module1 import *
func()  # 可用
bar()   # 不可用,抛异常
在模块导入中我们需要注意 循环导入问题同一个模块只会在第一次导入时执行其内部代码,再次导入该模块时,即便是该模块尚未加载完毕也不会执行内部代码在一个模块加载/导入的过程中导入另一个模块,而在另一个模块中又返回导入第一个模块中的名字,由于第一个模块尚未加载完毕,所以引用失败,抛出异常,

解决方法

方式一: 导入语句放到最后,保证在导入时,所有名字都已经加载过
方式二: 导入语句放到函数中,只有在调用函数时才会执行其内部代码

2. 包

包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py 文件,那么这个文件夹就称之为包。包属于模块的一种,因而包以及包内模块君是用来被导入的,

pool/                #顶级包
├── __init__.py     
├── futures          #子包
│   ├── __init__.py
│   ├── process.py
│   └── thread.py
└── versions.py      #子模块

2.1 绝对导入和相对导入

绝对导入以顶级包开始,相对导入 代表当前文件所在的目录,.代表当前文件的路径
绝对导入

# pool下的__init__.py  
from pool import versions

相对导入

#pool下的__init__.py  
from . import versions
相对导入只能在包内部使用,用相对导入不同目录下的模块事非法的
无论是 import 还是 form-import ,但凡是导入是带有节点的,点左边必须是包,否则语法报错

2.3 __all__

在使用包时同样支持from pool.fultures import *,毫无疑问*就是代表fultures.__init__.py中所有的名字,通过用变量__all__来控制*代表的意思
此时通过操作__init__.py,可以隐藏包内部的目录结构,降低使用难度,比如想让使用者直接使用

#futures下的__init__.py 
__all__=['process','thread']

无常
21 声望0 粉丝

« 上一篇
Python-函数