Python模块与包

一、模块

1、概述

Python中一个以.py结尾的源文件即为一个模块(Module)。

模块中可以包含变量、函数和类等。

通常把能够实现某一特定功能的代码放置在一个文件中作为一个模块。

模块可以提高代码的可维护性 与 可复用性,还可以避免命名冲突。

2、模块的分类

Python 中的模块分为三类,分别是:标准库模块、自定义模块、第三方模块。

3、创建模块

模块命名注意点:

  1. 要符合标识符命名规则

  2. 模块名(.py文件名)区分大小写

  3. 不要与标准库模块同名(一旦同名,Python会优先引入标准库模块)

创建如下模块文件:

├── main.py # main模块

└── my_multi.py # my_multi模块

└── my_add.py # my_add模块

创建一个模块my_add.py示例:

python 复制代码
num =100
def add(a, b):
    """求两个数的和"""
    return a + b

4、导入模块

1、全部导入 import as

导入模块的所有成员,

通过模块名.成员名的方式访问。

即使多次使用 import导入同一模块,模块也只会被导入一次。

1.1 语法

python 复制代码
import 模块名 [as 别名]

1.2 案例

在同一目录下创建一个main.py文件,在其中导入 my_add.py 模块并使用。

python 复制代码
# 导入模块
import my_add

# 使用模块
print(my_add.add(1, 2))
print(my_add.num)

也可以在导入模块时给模块起别名。

python 复制代码
# 导入模块
import my_add as a1

# 使用模块
print(a1.add(1, 2))
print(a1.num)

2、局部导入 from import as

指定导入模块的部分成员,直接通过成员名的方式访问。

只能使用其导入的成员,未导入的成员不能使用。

如果多个模块中存在重名成员,后一次导入会覆盖前一次导入。

2.1 语法

python 复制代码
from 模块名 import 成员名1[as 别名], 成员名2[as 别名],...

2.2 案例

⮚ 创建新的模块my_multi.py

python 复制代码
num =200
_str1="abc"
def multi(a, b):
    """求两个数的积"""
    return a * b

⮚ 只能使用导入的成员

python 复制代码
from my_add import add 
print(add(1, 2))
print(num) # NameError: name 'num' is not defined

⮚ 重名变量,后一次导入会覆盖前一次导入

python 复制代码
# 导入模块
from my_add import add,num    # my_add 中num=100
from my_multi import num    # my_multi 中num=200
# 使用模块
print(add(1, 2))
print(num)    # num=200

⮚ 通过别名区分不同模块的变量

python 复制代码
# 导入模块
from my_add import add,num as a1
from my_multi import num as m1
# 使用模块
print(add(1, 2))
print(a1) 
print(m1) 

3、局部导入 from import *

导入模块中所有不以单下划线开头的成员,直接通过成员名的方式访问。

3,1 语法

python 复制代码
from 模块名 import *

3.2 案例

python 复制代码
# 导入模块
from my_add import *

# 使用模块
print(add(1, 2))
print(num)
print(_str1)

4、allname

关于__all__:

• 在 Python 模块中,可通过 all 来控制 **from 模块 import ***能导入哪些内容。

all 的值可以是:列表、元组。

重点:all 的设置只针对****使用 from import * 导入模块时有效

关于__name__:

• __name__是每个 Python 模块(.py文件)都拥有的一个内置变量。

• 它的具体值取决于模块的运行方式:

(1). 作为主程序直接运行,name 的值是 main

(2). 作为模块被导入到其他程序中运行,__name__的模块的文件名(不带.py)。

4.1 all

使用 from import * 这种方式导入模块时,可以在被导入的模块中 使用 **all**设置哪些内容可以被导入。

重点:all 的设置只针对****使用 from import * 导入模块时有效

在my_add.py 中向__all__添加部分元素:

python 复制代码
__all__ = ["num","add"] #  内容必须要用引号引起来

num = 100
num1 = 200
_str1="abc"
def add(a, b):
    """求两个数的和"""
    return a + b

在main.py中以 **from my_add import ***这种方式导入模块中的内容。使用没在 all 中的变量时会报错:

python 复制代码
from my_add import *
print(add(1, 2))
print(num)
print(num1) # NameError: name 'num1' is not defined

而使用import my_add全局导入模块后可以正常使用所有元素:

python 复制代码
import my_add
print(my_add.add(1, 2))
print(my_add.num)
print(my_add.num1) 
4.2、name

在 Python 中,name 是一个特殊的内置变量

⮚ 当一个Python文件被直接运行时,该文件的__name__属性值为"main"。

⮚ 当一个Python文件作为模块被导入时,__name__属性会被设置为该模块的名称(即文件名,不包含 .py 后缀)。

1) 导入模块时测试代码被执行 有时我们会在模块中写一些测试代码,当模块被其他文件导入时这些测试代码会被执行。

在 my_add.py 中写一些测试代码:

python 复制代码
"""my_add.py"""
__all__ = ["num","add"]

num = 100
num1 = 200
_str1="abc"
def add(a, b):
    """求两个数的和"""
    return a + b

print(add(10,20))

main.py 中导入模块,发现 my_add.py 中的测试代码被执行了:

python 复制代码
"""main.py"""
import my_add

2) 使用 name == "main" 避免测试代码被执行 为了避免模块被导入时测试代码被执行,我们可以在被导入模块中添加对 name 属性的检查:

python 复制代码
"""my_add.py"""
__all__ = ["num","add"]

num = 100
num1 = 200
_str1="abc"
def add(a, b):
    """求两个数的和"""
    return a + b

print(__name__)
if __name__ == "__main__":
    print(add(10,20))

此时在 main.py 中导入模块,测试代码就不会被执行:

python 复制代码
"""main.py"""

import my_add

5、标准库模块

  1. Python 中的模块分为三类,分别是:标准库模块、自定义模块、第三方模块。

  2. 标准库模块:随着 Python 一起安装在我们电脑上的那些模块。

  3. 有一些标准库模块是用C语言实现的,这些用C语言实现的模块,又称:【内置模块】。

标准库模块保存在Python安装目录中的Lib文件夹中,但内置模块无法在Lib中看到。

6、模块搜索顺序

当导入一个模块时,会按照以下顺序进行查找:

(1) 当前目录。

(2) PYTHONPATH环境变量中的目录。

(3) 包含标准 Python 模块以及这些模块所依赖的任何 extension module 的目录。

可以使用以下方式查看模块搜索顺序:

python 复制代码
import sys

print(sys.path)

也可以通过 sys.path.append(路径) 向 sys.path 中临时添加路径。

python 复制代码
import sys

print(sys.path)
sys.path.append("./..")
print(sys.path)

7、dir()

dir() 是一个内置函数,主要用于列出对象的属性和方法,或者列出当前作用域中定义的名称,并以一个字符串列表的形式返回。

⮚ 当你将一个模块作为 dir() 的参数时,它会返回该模块中定义的名称列表,包括函数、类、变量等

python 复制代码
import math

# 查看math模块下的  
print(dir(math))

⮚ 当你将一个对象作为 dir() 的参数时,它会返回该对象的属性和方法列表。

python 复制代码
class MyClass:
    def __init__(self):
        self.x = 1
        self.y = 2

    def method1(self):
        pass
obj = MyClass()
print(dir(obj))

⮚ 当你不传递任何参数调用 dir() 时,它会列出当前作用域中定义的名称,包括变量、函数、类等

python 复制代码
def my_function():
    pass
variable = 10
print(dir())

二、包

1、概述

包是一种管理 Python 模块命名空间的形式

• 包是一种组织模块的方式,包中可以包含:各种模块、子包、其他资源等。

• 在 Python 中,【包含__init__.py 的文件夹】就是一个包(Package)。

• 我们通常会把【某个特定功能相关的所有模块】放入一个包中。

• 使用包可以进一步提升代码的:可维护性、可复用性,便于管理大型项目。

2、包与模块的关系

• 一个模块就是一个.py文件 ,包是用来"管理模块"的目录(文件夹)。

• 一个包中可以有多个模块,也可以有多个子包。

3、包的分类

Python 中的包分为三类,分别是:标准库包、自定义包、第三方包。

4、创建包

包命名注意点:

  1. 要符合标识符命名规范。

  2. 包名区分大小写(建议全部使用小写字母)

  3. 不要与标准库包同名。

init.py 可以只是一个空文件,也可以执行包的初始化代码或设置 all 变量。

在PyCharm创建一个graphic文件夹并在其中创建circle.pyrectangle.py 文件。

其中 init.py 文件暂时为空。 circle.pyrectangle.py 文件写入代码。

在包外创建一个 main.py 文件。 整体结构如下,其中 graphic 为一个包:

circle.py

python 复制代码
"""circle.py"""

radius = 10
PI = 3.1415926

def area(radius):
    return PI * radius * radius

def perimeter(radius):
    return 2 * PI * radius

rectangle.py

python 复制代码
"""rectangle.py"""

rectangle_width = 10
rectangle_height = 10

def area(width, height):
    return width * height

def perimeter(width, height):
    return 2 * (width + height)

5、导入包

⭐关于 init.py 文件

  1. init.py 是包的初始化文件,在包被导入时init.py 会被自动调用

  2. init.py 中可以编写一些包的初始化逻辑

  3. init.py 中所定义的内容,会被 from 包名 import * 形式全部引入

  4. init.py 中也可以使用 all 来控制包中的哪些模块可以用 **from 包名 import ***这种方式引入

1、全局导入import

导入包中模块的所有成员

1.1 语法

python 复制代码
import 包名.模块名 [as 别名]

1.2 调用方式 :包名.模块名.成员名

python 复制代码
import graphic.circle

print(graphic.circle.area(10))  # 314.15926

**注意:**使用 import 时,除最后一项外都必须是包。

最后一项可以是模块或包,但不能是类、函数或变量。

如果最后一项是包,那么必须在被导入包的__init__.py文件中,指定导入包中的哪些模块。

这是python导包的一个优化机制,避免导入过多模块。

并且在__init__.py中指定导入模块的时候,建议使用相对路径

python 复制代码
from . import circle

如果是绝对路径,那么他会把导入的模块circle作为顶级模块,直接从sys.path中去找circle模块,而不是找graphic.circle,

python 复制代码
import circle

2、局部导入包下的模块 from import as

从包中导入模块

2.1 语法

python 复制代码
from 包名import模块名 [as 别名]

2.2 调用方式 :模块名.成员名

python 复制代码
from graphic import circle

print(circle.area(10))  # 314.15926

3、局部导入包下模块的成员 from import as

从包中模块导入功能

3.1 语法

python 复制代码
from 包名.模块名 import 成员名 [as 别名]

3.2 调用方式 : 成员名

python 复制代码
from graphic.circle import area

print(area(10))  # 314.15926

4、局部导入包下模块的成员 from 包名.模块名 import *

此种导入方式中,如果模块里有__all__,则导入的成员里也要受__all__控制

4.1 语法

python 复制代码
from 包名.模块名 import *

4.2 调用方式 : 成员名

python 复制代码
from graphic.circle import area

print(area(10))  # 314.15926
perimeter()

5、局部导入 from import * 从包中导入模块

当我们使用 from import * 时,Python并不会查找并导入包的所有子模块,因为这将花费很长的时间,并且可能会产生我们不想要的副作用。

唯一的解决办法是提供包的显式索引。如果包的 init.py 中定义了 all,运行 from import * 时,它就是被导入的模块名列表。

⭐关于 init.py 文件

  1. init.py 是包的初始化文件,在包被导入时,init.py 会被自动调用

  2. init.py 中可以编写一些包的初始化逻辑

  3. init.py 中所定义的内容,会被 from 包名 import * 形式全部引入

  4. init.py 中也可以使用 all 来控制包中的哪些模块可以用 from 包名 import * 这种方式引入

5.1 语法

python 复制代码
from 包名 import *

5.2 调用方式 :模块名.功能名

init.py 中添加如下内容:

python 复制代码
__all__ = ["circle"] # 注意:如果不加会无法导包

main.py 中使用 from import * 导入模块:

python 复制代码
from graphic import *

print(circle.area(10))  # 314.15926
print(rectangle.area(10))  # 报错

6、引入子包

以上引入方式,都可以用于引入子包,只需要在包名的后面跟上子包名即可,

在trade包中创建一个子包hello,其中包含h1模块:

python 复制代码
└── graphic/
    └── hello/
         ├── __init__.py
         └── h1.py
    ├── __init__.py
    ├── circle.py
    └── rectangle.py
    └── demo.py

h1模块内容如下:

python 复制代码
def say_hello():
    print('你好')

引包示例:

python 复制代码
from graphic.hello.h1 import say_hello

say_hello()

7、常用标准库(包)

标准库指的是在安装Python时就一同被安装的库。这些库经过精心挑选和开发,旨在为Python开发者提供通用且强大的工具集,涵盖各种不同的应用领域。

|---------------------|------------------------------------------------------------|
| 名称 | 说明 |
| os | 多种操作系统接口。 |
| sys | 系统相关的形参和函数。 |
| time | 时间的访问和转换。 |
| datetime | 提供了用于操作日期和时间的类。 |
| math | 数学函数。 |
| random | 生成伪随机数。 |
| re | 正则表达式匹配操作。 |
| json | JSON 编码器和解码器。 |
| collections | 实现了一些专门化的容器,提供了对 Python 的通用内建容器 dict、list、set 和 tuple 的补充。 |
| functools | 高阶函数,以及可调用对象上的操作 |
| hashlib | 安全哈希与消息摘要。 |
| urllib | URL 处理模块。 |
| smtplib | SMTP 协议客户端,邮件处理。 |
| zlib | 与 gzip 兼容的压缩。 |
| gzip | 对 gzip 文件的支持。 |
| bz2 | 对 bzip2 压缩算法的支持。 |
| multiprocessing | 基于进程的并行。 |
| threading | 基于线程的并行。 |
| copy | 浅层及深层拷贝操作。 |
| socket | 低层级的网络接口。 |
| shutil | 提供了一系列对文件和文件集合的高阶操作,特别是提供了一些支持文件拷贝和删除的函数。 |
| glob | Unix 风格的路径名模式扩展。 |

更多标准库可参考https://docs.python.org/zh-cn/3/library/index.html

8、引入第三方库(包)

当需要使用Python中没有内置的库时,可以通过以下方式安装第三方库

1、概述

• PyPI 是是 Python 官方推荐、官方维护的包发布与分发平台(https://pypi.org

• pip是Python包管理工具,该工具提供了对 Python 包的查找、下载、安装、卸载的功能。

• pip 默认的源是 Python Package Index(PyPI),其地址为https://pypi.org/simple/ ,如果下载比较慢,还可以指定其它的源。

⮚ 阿里云:http://mirrors.aliyun.com/pypi/simple/

⮚ 中国科技大学: https://pypi.mirrors.ustc.edu.cn/simple

⮚ 清华大学:https://pypi.tuna.tsinghua.edu.cn/simple/

2、pip常用命令

|------------------------------------|--------------------------|
| 命令 | 说明 |
| pip install 包名 | 安装指定的包。具体包名是什么可以到PyPI上查找 |
| pip install -i 镜像地址 包名 | 临时使用镜像地址 安装指定包。 |
| pip config set global.index-url 地址 | 设置 pip 所使用的镜像地址。 |
| pip config list | 查看当前环境的 pip 配置。 |
| pip config unset global.index-url | 让 pip 恢复使用官方默认的地址。 |
| pip list | 列出当前环境中,已安装的所有第三方包。 |
| pip uninstall 包名 | 从当前环境中卸载指定的第三方包。 |

9、打包自己的库并安装

1、先安装 setuptools 库

如果不安装setuptools库,后续打包时可能会遇到报错 ModuleNotFoundError: No module named 'distutils',所以可以提前安装 setuptools 库。

在命令提示符中执行如下命令:

python 复制代码
pip install setuptools

2、在包外创建一个 setup.py 文件

3、setup.py 中添加如下内容

python 复制代码
from distutils.core import setup

setup(
    name="graphic",  # 需要打包的名字
    version="1.0",  # 版本
    py_modules=["graphic.circle", "graphic.rectangle"],  # 需要打包的模块
)

4、在 setup.py 同级目录下进行构建

python 复制代码
python setup.py build

5、也可以生成压缩包

python 复制代码
python setup.py sdist

6、pip命令安装自己打的库

python 复制代码
pip install path_to_your_package/dist/your_package_name-0.1.tar.gz

7、Pycharm安装自己打的包库

三、全局环境 vs 虚拟环境

1、概述

以安装一个 三方包numpy包为例(注意:请务必使用管理员身份运行 cmd)

💡思考:numpy安装到哪里去了呢? ------------ 全局环境

• 什么是环境? ------ 所谓环境就是指:python 解释器 + 依赖包。

• Python 环境分类两种,分别是全局环境(系统环境)、虚拟环境。

所有项目共用全局环境容易互相影响和干扰,虚拟环境可以解决这个问题,二者结构如下图:

  1. 图中的 Python 安装目录中的文件,构成了全局环境(系统环境)。

  2. 图中的.venv中的文件构成了虚拟环境。

  3. 虚拟环境有自己独立的一套:Python 解释器、pip 命令、第三方依赖包,不和其它项目产生干扰。

  4. 虚拟环境和全局环境共用的东西,只有标准库。
    在cmd中不做任何处理,直接通过pip安装的包,都是安装在了全局环境中,

如果想在虚拟环境中安装包,需要切到虚拟环境目录后,通过activate命令切换到虚拟环境。

备注:使用deactivate可以退出虚拟环境。

2、创建全局环境项目

通过 Pycharm 创建项目时,进行如下配置,即可创建全局环境:

在全局环境中安装好这两个包:numpy、pyfiglet,随后进行测试:

python 复制代码
# 使用安装在全局环境中的第三方包numpy
import numpy as npresult = np.random.randint(10, 100, size=10)
print(result)
print(type(result))
print(result.max())
print(result.min())

# 使用安装在全局环境中的第三方包pyfiglet
from pyfiglet import figlet_format
result = figlet_format('hello')
print(result)

# 使用全局的标准库
from collections import Counter
list1 = [10, 20, 30, 40, 20, 30, 20, 30, 10, 10, 10]
res = Counter(list1)
print(res)

**结论:**基于全局环境的项目,可以使用:全局环境中的第三方包,也可以使用全局的标准库。

3、创建虚拟环境项目

通过 Pycharm 创建项目时,进行如下配置,即可创建虚拟环境:

给虚拟环境安装第三方包的方式有三种:

1、通过 cmd 安装

1.1 先切换到虚拟环境

1.2 随后会切换到虚拟环境

1.3 随后安装自己想要的包(例如:faker)

2、通过 Pycharm 中的命令行窗口安装

2.1 在 Pycharm 中打开命令行,会自动激活当前目录的虚拟环境

2.2 随后安装自己想要的包(例如:jieba)

3、通过 Pycharm 提供的可视化工具安装

3.1 点击 Pycharm 右下角,随后选择解析器设置

3.2 随后点击加号+

3.3 在搜索框里输入自己想安装的包(例如:cn2an),随后点击安装即可

测试使用虚拟环境的第三方包

python 复制代码
# 使用安装在当前虚拟环境中的第三方包faker
from faker import Faker
f = Faker('zh_CN')
print(f.name())
print(f.address())
print(f.phone_number())

# 使用安装在当前虚拟环境中的第三方包jieba
import jieba
result = jieba.lcut('南京市长江大桥')
print(result)

# 使用安装在当前虚拟环境中的第三方包cn2an
import cn2an
print(cn2an.cn2an('九千七百四十三'))


# 使用全局的标准库
from collections import Counter
list1 = [10, 20, 30, 40, 20, 30, 20, 30, 10, 10, 10]
res = Counter(list1)
print(res)

**结论:**基于虚拟环境的项目,可以使用:虚拟环境中的第三方包,也可以使用全局的标准库。

相关推荐
数智化码农1 小时前
半导体制造人力资源数字化选型:适配双用工体系,兼顾合规与人效
大数据·运维·python·制造
statistican_ABin1 小时前
中国婚姻与生育观念变迁分析报告
python
雪落漂泊1 小时前
C++智能指针
开发语言·jvm·c++
清水白石0081 小时前
别被 `Process.start()` 骗了:Python multiprocessing 从面试题到线上生产的进程启动机制实战
开发语言·python
geovindu1 小时前
java: Task Scheduler
java·开发语言·后端
神奇小梵1 小时前
java的特殊语法点,与常规语言相异的点
java·开发语言
愚公移山填海2 小时前
【无标题】
笔记·python·学习·pycharm
bnmoel2 小时前
C++ 基础入门篇(二):引用
开发语言·c++·引用·底层
天远API2 小时前
零信任架构实战:基于天远公安三要素即时版构建自动化理赔合规网关
人工智能·python·架构·自动化