yyz notes yyz notes
首页
  • RBAC权限设计
  • 架构图标设计
  • 账号体系
  • python基础
  • python高级
  • python模块
  • python设计模式
  • python数据结构与算法
  • django
  • django-DRF
  • flask
  • 直接设计开源pip包
  • 直接设计开源项目
  • python示例题/脚本
  • python面试题
  • golang基础
  • golang高级
  • golang常用组件
  • gin框架
  • es6
  • javascript
  • react
  • vue
  • TypeScript
  • mysql
  • redis
  • minio
  • elasticsearch
  • mongodb
  • 消息队列
  • 自动化测试
  • 操作系统

    • linux
    • windows
  • nginx
  • docker
  • k8s
  • git
  • ldap
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

益章

可乐鸡翅
首页
  • RBAC权限设计
  • 架构图标设计
  • 账号体系
  • python基础
  • python高级
  • python模块
  • python设计模式
  • python数据结构与算法
  • django
  • django-DRF
  • flask
  • 直接设计开源pip包
  • 直接设计开源项目
  • python示例题/脚本
  • python面试题
  • golang基础
  • golang高级
  • golang常用组件
  • gin框架
  • es6
  • javascript
  • react
  • vue
  • TypeScript
  • mysql
  • redis
  • minio
  • elasticsearch
  • mongodb
  • 消息队列
  • 自动化测试
  • 操作系统

    • linux
    • windows
  • nginx
  • docker
  • k8s
  • git
  • ldap
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • python基础

    • python概述

    • python环境搭建

    • python基础语法

    • python关键字与标识符

    • python流程控制

    • python函数

    • python内置函数

    • python面向对象

    • python模块与包

      • 模块与包
        • 简介
        • 1. 模块
          • 1.1 导入模块
          • import
          • from
          • 限制模块函数的调用_main_
          • *模块的搜索路径*
          • 1.2 编写自定义模块
          • __all__变量用法
        • 2. 包
          • 2.1 创建包,导入包
          • 创建包
          • 导入包
        • 3. 查看模块(变量、函数、类)方法
          • 3.1 查看模块成员:dir()函数
          • 3.2 查看模块成员:__all__变量
          • 3.3 查看文档:__doc__属性
          • 3.4 查看模块的源文件路径:_file_属性
    • python文件IO与OS

    • python异常处理机制

  • python高级

  • python模块

  • python设计模式

  • python数据结构与算法

  • django

  • django-DRF

  • flask

  • 自己设计开源pip包

  • 自己设计开源项目

  • python小示例

  • python面试题

  • python
  • python基础
  • python模块与包
YiZhang-You
2023-05-17
目录

模块与包

# 简介

python 提供了强大的模块支持,主要体现在,不仅 Python 标准库中包含了大量的模块(称为标准模块),还有大量的第三方模块,开发者自己也可以开发自定义模块。通过这些强大的模块可以极大地提高开发者的开发效率。

# 1. 模块

# 1.1 导入模块

# import

import 模块名
	模块名.变量  模块名.函数  模块名.类

import 模块名 as 别名
1
2
3
4

# from

from 模块名 import 变量/函数/类

from 模块名 import * 该模块中所有的内容
	但是如果想限制获取的内容,可以在模块使用__all__[使用*可以访问到内容]

from  模块名 import 成员名 as 别名

from tbjx import read1,read2,name  # 导入多个模块
1
2
3
4
5
6
7
8

无论是import还是from的形式,都会将模块内容进行加载

# 限制模块函数的调用__main__

不想让模块中的某些代码执行, 可以用__name__属性来使程序仅调用模块中的一部分。

每一个模块中都有一个__name__属性, 当其值等于__main__时, 表明该模块自身在执行, 否则被引入了其他文件。

当前文件如果为程序的入口文件, 则__name__属性的值为__main__。

if __name__ == '__main__':
    print('这是Titan模块')
else:
    def sayGood():
        print('good')
 
 
    def sayNice():
        print('nice')
 
 
    def sayBad():
        print('bad')
 
 
    age = 20
    name = 'titan'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# *模块的搜索路径*

模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块

#模块的查找顺序
1、在第一次导入某个模块时(比如spam),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
    ps:python解释器在启动时会自动加载一些模块到内存中,可以使用sys.modules查看
2、如果没有,解释器则会查找同名的内置模块
3、如果还没有找到就从sys.path给出的目录列表中依次寻找spam.py文件。
#需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。虽然每次都说,但是仍然会有人不停的犯错。 
#在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载。
>>> import sys
>>> sys.path.append('/a/b/c/d')
>>> sys.path.insert(0,'/x/y/z') #排在前的目录,优先被搜索
注意:搜索时按照sys.path中从左到右的顺序查找,位于前的优先被查找,sys.path中还可能包含.zip归档文件和.egg文件,python会把.zip归档文件当成一个目录去处理,
#首先制作归档文件:zip module.zip foo.py bar.py 
import sys   
sys.path.append('module.zip')
# sys.path获取到的是一个列表.所以我们可以执行列表的操作
import foo
import bar
#也可以使用zip中目录结构的具体位置
sys.path.append('module.zip/lib/python')
#windows下的路径不加r开头,会语法错误
sys.path.insert(0,r'C:\\Users\\Administrator\\PycharmProjects\\a')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 1.2 编写自定义模块

'''
add:相加
Subtraction:减法
'''
number = 100
__all__ = ['add', 'subtraction']  # 只让调用者访问这二个方法 ,这个__all__是为from x import *号设置的

def add(*args):
    if len(args) > 1:
        sum = 0
        for i in args:
            sum += i
        return sum
    else:
        print("参数一定要大于一位数add")
        return 0

def subtraction(*args):
    if len(args) > 1:
        m = args[0] * 2  # 提供args的第一个元素*2在减第一个,就变成了正数
        for i in args:
            m -= i
        return m
    else:
        print("参数一定要大于一位数add")
        return 0
__all__ = ['add', 'subtraction']  # 只让调用者访问这二个方法 ,这个__all__是为from x import *号设置的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# __all__变量用法

all 变量,该变量的值是一个列表,存储的是当前模块中一些成员(变量、函数或者类)的名称。通过在模块文件中设置 all 变量,当其它文件以“from 模块名 import *”的形式导入该模块时,该文件中只能使用 all 列表中指定的成员。

也就是说,只有以“from 模块名 import *”形式导入的模块,当该模块设有 all 变量时,只能导入该变量指定的成员,未指定的成员是无法导入的。

def say():
    print("人生苦短,我学Python!")
def CLanguage():
    print("C语言中文网:<http://c.biancheng.net>")
def disPython():
    print("Python教程:<http://c.biancheng.net/python>")
__all__ = ["say","CLanguage"]

# 可见,__all__ 变量只包含 say() 和 CLanguage() 的函数名,不包含 disPython() 函数的名称。此时直接执行  test.py 文件,其执行结果为:

人生苦短,我学Python!
C语言中文网:<http://c.biancheng.net>
Traceback (most recent call last):
  File "C:/Users/mengma/Desktop/2.py", line 4, in <module>
    disPython()
NameError: name 'disPython' is not defined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

再次声明,all 变量仅限于在其它文件中以“from 模块名 import *”的方式引入。也就是说,如果使用以下 2 种方式引入模块,则 all 变量的设置是无效的。

  • 以“import 模块名”的形式导入模块。通过该方式导入模块后,总可以通过模块名前缀(如果为模块指定了别名,则可以使用模快的别名作为前缀)来调用模块内的所有成员(除了以下划线开头命名的成员)。

    #demo.py
    def say():
        print("人生苦短,我学Python!")
    def CLanguage():
        print("C语言中文网:<http://c.biancheng.net>")
    def disPython():
        print("Python教程:<http://c.biancheng.net/python>")
    __all__ = ["say"]
    #test.py
    import demo
    demo.say()
    demo.CLanguage()
    demo.disPython()
    
    人生苦短,我学Python!
    C语言中文网:<http://c.biancheng.net>
    Python教程:<http://c.biancheng.net/python>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  • 以“from 模块名 import 成员”的形式直接导入指定成员。使用此方式导入的模块,all 变量即便设置,也形同虚设。

    from demo import say
    from demo import CLanguage
    from demo import disPython
    say()
    CLanguage()
    disPython()
    
    人生苦短,我学Python!
    C语言中文网:<http://c.biancheng.net>
    Python教程:<http://c.biancheng.net/python>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

# 2. 包

实际开发中,一个大型的项目往往需要使用成百上千的Python (opens new window)模块,如果将这些模块都堆放在一起,势必不好管理。而且,使用模块可以有效避免变量名或函数名重名引发的冲突,但是如果模块名重复怎么办呢?因此,Python提出了包(Package)的概念。

什么是包呢?简单理解,包就是文件夹,只不过在该文件夹下必须存在一个名为“init.py” 的文件。

注意,这是 Python 2.x 的规定,而在 Python 3.x 中,init.py 对包来说,并不是必须的。

每个包的目录下都必须建立一个 init.py 的模块,可以是一个空模块,可以写一些初始化代码,其作用就是告诉 Python 要将该目录当成包来处理。

注意,init.py 不同于其他模块文件,此模块的模块名不是 init,而是它所在的包名。例如,在 settings 包中的 init.py 文件,其模块名就是 settings。

# 2.1 创建包,导入包

# 创建包

《Python包 (opens new window)》一节中已经提到,包其实就是文件夹,更确切的说,是一个包含“init.py”文件的文件夹。因此,如果我们想手动创建一个包,只需进行以下 2 步操作:

  1. 新建一个文件夹,文件夹的名称就是新建包的包名;
  2. 在该文件夹中,创建一个 init.py 文件(前后各有 2 个下划线‘_’),该文件中可以不编写任何代码。当然,也可以编写一些 Python (opens new window) 初始化代码,则当有其它程序文件导入包时,会自动执行该文件中的代码(本节后续会有实例)。

# 导入包

通过前面的学习我们知道,包其实本质上还是模块,因此导入模块的语法同样也适用于导入包。无论导入我们自定义的包,还是导入从他处下载的第三方包,导入方法可归结为以下 3 种:

  1. import 包名[.模块名 [as 别名]]
  2. from 包名 import 模块名 [as 别名]
  3. from 包名.模块名 import 成员名 [as 别名]

用 [] 括起来的部分,是可选部分,即可以使用,也可以直接忽略。

注意,导入包的同时,会在包目录下生成一个含有 init.cpython-36.pyc 文件的 pycache 文件夹。

# 3. 查看模块(变量、函数、类)方法

# 3.1 查看模块成员:dir()函数

通过 dir() 函数,我们可以查看某指定模块包含的全部成员(包括变量、函数和类)。注意这里所指的全部成员,不仅包含可供我们调用的模块成员,还包含所有名称以双下划线“__”开头和结尾的成员,而这些“特殊”命名的成员,是为了在本模块中使用的,并不希望被其它文件调用。

这里以导入 string 模块为例,string 模块包含操作字符串相关的大量方法,下面通过 dir() 函数查看该模块中包含哪些成员:

import string
print(dir(string))

['Formatter', 'Template', '_ChainMap', '_TemplateMetaclass', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_re', '_string', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']
1
2
3
4

显然通过列表推导式,可在 dir() 函数输出结果的基础上,筛选出对我们有用的成员并显示出来。

import string
print([e for e in dir(string) if not e.startswith('_')])

['Formatter', 'Template', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']
1
2
3
4

# 3.2 查看模块成员:__all__变量

除了使用 dir() 函数之外,还可以使用 all 变量,借助该变量也可以查看模块(包)内包含的所有成员。

import string
print(string.__all__)

['ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace', 'Formatter', 'Template']
1
2
3
4

和 dir() 函数相比,all 变量在查看指定模块成员时,它不会显示模块中的特殊成员,同时还会根据成员的名称进行排序显示。

不过需要注意的是,并非所有的模块都支持使用 all 变量,因此对于获取有些模块的成员,就只能使用 dir() 函数。

# 3.3 查看文档:__doc__属性

无论是函数还是类,都可以使用 doc 属性获取它们的说明文档,模块也不例外。

以 my_package 包 module1 模块中的 display() 函数为例,我们尝试用 doc 变量获取其说明文档:

import my_package
print(my_package.module1.display.__doc__)
1
2

那么,如果使用 help() 函数或者 doc 属性,仍然无法满足我们的需求,还可以使用以下 2 种方法:

  1. 调用 file 属性,查看该模块或者包文件的具体存储位置,直接查看其源代码(后续章节或详细介绍);
  2. 对于非自定义的模块或者包,可以查阅 Python (opens new window) 库的参考文档 https://docs.python.org/3/library/index.html。

# 3.4 查看模块的源文件路径:__file__属性

当指定模块(或包)没有说明文档时,仅通过 help() 函数或者 doc 属性,无法有效帮助我们理解该模块(包)的具体功能。在这种情况下,我们可以通过 file 属性查找该模块(或包)文件所在的具体存储位置,直接查看其源代码。

import my_package
print(my_package.__file__)

# C:\\Users\\mengma\\Desktop\\my_package\\__init__.py
1
2
3
4

由此,通过调用 file 属性输出的绝对路径,我们可以很轻易地找到该模块(或包)的源文件。

注意,并不是所有模块都提供 file 属性,因为并不是所有模块的实现都采用 Python 语言,有些模块采用的是其它编程语言(如 C 语言)。

编辑 (opens new window)
上次更新: 2023/05/17, 23:08:21
python魔法方法
python绝对路径和相对路径

← python魔法方法 python绝对路径和相对路径→

最近更新
01
配置yun源
05-24
02
linux-配置python虚拟环境
05-24
03
linux文件目录管理
05-24
更多文章>
Theme by Vdoing | Copyright © 2023-2023 yizhang | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式