1 基本概念
-
模块:
为了让代码更容易维护,提高代码的重用价值;
可以将一组相关功能的代码写入一个单独的.py 文件中,供外界使用;
这个.py 文件就可以称为一个模块; -
包:
包是一个有层次的文件目录结构,它定义了由 n 个模块或 n 个子包;
包含init.py文件目录,这个目录下一定得有这个init.py文件和其他模块或子包 -
库:
完成一定功能的代码集合;
具体表现可以是一个模块,也可以是包; -
框架:
从库功能角度来看,解决一个开放性问题而设计的具有一定约束性的支撑结构
通过一个框架,可以快速实现一个问题解决的骨架;到时按照框架角色去填充,交互就可以完成一个质量好,维护性高的项目;
2 包和模块的作用
- 有效对程序进行功能分解和封装,方便代码的管理和维护
- 防止同一模块内的命名重复问题
3 创建包和模块
-
创建一个模块
即创建一个.py 文件即可
- 创建一个包
即创建一个文件夹,且应该创建一个init.py文件。(Python3.3之后创建包可以不用带上init.py)
4 查看包或模块位置及对应 API
import json
# 查看位置
print(json.__file__)
# 查看API 内容
print(dir(json))
>>>>打印结果
/usr/local/Cellar/python3/3.6.4_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py
['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_default_decoder', '_default_encoder', 'codecs', 'decoder', 'detect_encoding', 'dump', 'dumps', 'encoder', 'load', 'loads', 'scanner']
5 导入包/模块
5.1 常规导入
1. 单个导入
import module_name
or import package_name
通过点语法定位到所需的模块文件;
导入一个包时,会自动执行init.py 文件代码
2. 多个导入
文件所在位置是 Test1.py
# Test1.py
import Test2, package1.Test3, package1.package_sub1.Test4
# 使用时
print(package1.package_sub1.Test4.name)
3. 导入时起别名
- 场景一:简化资源访问前缀
# Test1.py
import package1.package_sub1.Test4 as test4
# 使用时
print(test4.name)
场景二:增加程序的扩展性
优化前
if file_extension == "txt":
import txt_parse
txt_parse.open()
txt_parse.read()
txt_parse.close()
elif file_extension == "doc"
import doc_parse
doc_parse.open()
doc_parse.read()
doc_parse.close()
优化后
if file_extension == "txt":
import txt_parse as p
elif file_extension == "doc"
import doc_parse as p
p.open()
p.read()
p.close()
4. 仅导入包名
import package1
- 默认不会导入任何模块
- 解决方案:
1. 在init文件中,再次导入需要的模块
2. 应该以 from... import...的形式导入
# package1 内的 __init__.py
import package1.Test3 # 这里需要写绝对路径
# Test1.py
import package
print(package1.Test3.name)
5.2 from 语句导入
1. 作用
只导入一个模块或包种的某个部分
2. 语法
# 从哪里,导入哪些资源到当前位置
from A import B[as C]
注意:
- 只能从大的地方找小的东西:A 的范围 > B 的范围
- 按照大小顺序可以将几个资源排序:包 > 模块 > 模块资源
- 注意面向关系:
* 包里面只能看到模块,看不到模块资源
* 模块里面只能看到模块资源
3. 可能的组合为
文件位置结构3.1 从包中导入模块
- 单个
Test1.py
name = "Test1"
from package1 import Test3
print(Test3.name) # 直接使用模块名
>>>>打印结果
Test3
- 多个
Test1.py
name = "Test1"
from package1 import Test3, Test3_1
print(Test3.name)
print(Test3_1.name)
>>>>打印结果
Test3
Test3_1
- 起别名
Test1.py
name = "Test1"
from package1 import Test3 as t3, Test3_1 as t3_1
print(t3.name)
print(t3_1.name)
>>>>打印结果
Test3
Test3_1
- 包有多个层级
Test1.py
name = "Test1"
from package1.package_sub1 import Test4 as t4, Test4_1 as t4_1
print(t4.name)
print(t4_1.name)
>>>>打印结果
Test4
Test4_1
3.2 从模块中导入模块资源
- 单个
Test2.py
name2 = "Test2"
age2 = 2
Test1.py
name1 = "Test1"
age1 = 1
from Test2 import name2 # 只是导入 Test 模块中的 name 资源
print(name2)
>>>>打印结果
Test2
- 多个
Test1.py
name1 = "Test1"
age1 = 1
from Test2 import name2, age2
print(name2)
print(age2)
>>>>打印结果
Test2
2
- 起别名
Test1.py
name1 = "Test1"
age1 = 1
from Test2 import name2 as n2, age2
print(n2)
print(age2)
>>>>打印结果
Test2
2
- 模块有多个层级
Test1.py
name1 = "Test1"
age1 = 1
from package1.Test3 import name3, age3
print(name3)
print(age3)
>>>>打印结果
Test3
3
6 通配符*
6.1 from 模块 import *
- *号代表是所有 非下划线 开头资源导入到当前位置
- 配合变量
__all__
使用
2.1__all__
是一个列表
2.2 其中的每个元素都是字符串__all__ = ["name", "age"]
2.3__all__
列表内容代表到时 * 号能够匹配到的资源 - 慎用:因为你无法预知到时候导入哪些内容到当前位置,容易产生同名变量被覆盖的错误
Test2.py
name2 = "Test2"
age2 = 2
Test1.py
name1 = "Test1"
age1 = 1
from Test2 import *
print(name2)
print(age2)
>>>>打印结果
Test2
2
- 配合
__all__
使用
Test2.py
__all__ = ["name2"] # 进行了限制处理
name2 = "Test2"
age2 = 2
Test1.py
name1 = "Test1"
age1 = 1
from Test2 import *
print(name2)
print(age2)
>>>>打印结果
Test2
Traceback (most recent call last):
File "/Users/xxx/Desktop/PythonProject/PackageAndModule/Test1.py", line 9, in <module>
print(age2)
NameError: name 'age2' is not defined
- 同名变量覆盖
正常情况
Test2.py
# __all__ = ["name"]
name = "Test2"
age = 2
Test1.py
name = "Test1"
age = 1
from Test2 import *
print(name)
print(age)
>>>>打印结果
Test2
2
异常情况,同名变量被覆盖
Test2.py
# __all__ = ["name"]
name = "Test2"
age = 2
Test1.py
from Test2 import *
name = "Test1"
age = 1
print(name)
print(age)
>>>>打印结果
Test1
1
6.2 from 包 import *
- 基本同上,主要是导入包时,会去识别__init__.py文件内的
__all__
变量 - 此时的
__all__
列表内字符串元素描述的是包内模块名__all__ = ["module1", "module2"]
-
使用例子:
package1 文件夹中的 __init__.py
__all__ = ["Test3"] #限制提供给外界的模块
Test3.py
name3 = "Test3"
age3 = 3
Test1.py
name = "Test1"
age = 1
from package1 import *
print(Test3.name3)
>>>>打印结果
Test1
- 注意,如果package1 文件夹中的 init.py文件内没有指明
__all__
变量,则Test1.py 文件的代码会报错
Question:
- import 和 from... import...有什么区别
- 模块,函数,包,类按照大小顺序排序是
- form A import B 中 A 和 B 的填写有什么注意事项
网友评论