Python学习笔记(九)模块和包

“Life is short, You need Python” – Bruce Eckel

Environment

  • OS: macOS Mojave
  • Python version: 3.7
  • IDE: Jupyter Notebook


0. 写在前面

“Python 自带电池”,指的就是 Python 标准库,它随着 Python 的安装被安装到了本地,其中包含了许多好用高效的内置模块们,如 os、pickle 等。

“You don’t have to reinvent the wheel.” Python 有大量的第三方库,如进行数据分析,常会用到 numpy、scipy、pandas 等包,有称呼 numpy 和 scipy 作科学计算库。此外,还有爬虫框架(scrapy等),深度学习框架(tensorflow、pytorch等),web应用框架(flask、django等)。

1. 概念

在日常使用中,不管是 模块 还是 还是 或是框架import 就完事了。但搞搞清楚区别还是要的。

  • 一个以 .py 结尾的 Python 代码文件就是一个 模块(module),实质上是变量、函数和类的集合。这些模块的路径为 /anaconda3/envs/环境名/lib/python3.7/

在这里插入图片描述在这里插入图片描述

  • 包(package) 就是包含一些模块文件和一个 __init__.py 文件的目录,实质上是模块的集合。为了在实际开发中方便地管理许多不同的模块,将模块们放进不同的目录。包的路径为 /anaconda3/envs/环境名/lib/python3.7/site-packages/

在这里插入图片描述

  • 库(library) 强调的是功能性,表示完成一定功能的代码的集合,可以是一些模块的集合,如内置模块们来自 Python 标准库;可以是一个包,如numpy 和 scipy 又被称为科学计算库。区别于 Python 库,其他来源的库都可以称为为“第三方库”。

  • 框架(framework) 是库的集合,提供解决问题的一整套方案。与 的不同之处在于,框架 存在较强的约束性,需要按照其中的规则办事,像是一门独立的语言。


2. 导入

  • import 模块名 [as 别名] 导入整个模块,可以在一行导入多个模块。通过 模块名或别名.函数名或变量名或类名 调用
import random, math

random.seed(0)
print(random.randint(1, 3)) # 2
print(math.e) # 2.718281828459045
  • from 模块名 import 函数名或变量名或类名 [as 别名] 导入模块中特定的函数或变量或类,调用时可以省略模块名;拒绝使用 from 模块名 import * 导入模块中所有的方式。
from random import randint

# 随机从 1 到 3 的整数中返回一个
res = randint(1, 3)

若导入的函数名(或变量名或类名)与已有的同名,将发生覆盖。可见,from 模块名 import * 更容易带来麻烦,因此别这么干。

e = 666

from math import e

print(e) # 2.718281828459045

3. 创建

3.1 创建模块

关注两个属性,__name__、__doc__ 和 __all__

3.1.1 name

在 Python 执行文件中运行 __name__

print(__name__) # 输出 __main__

在编写模块时,其中有一些代码,如测试代码,只希望在模块单独作为程序运行时被执行,可以放在 if __name__ == '__main__:' 中,建议格式如下

def main_or_test():
	# 模块单独作为程序运行时,要执行的代码
	pass

if __name__ == '__main__':
	main_or_test()

如下编写一个模块 bar,放在当前 Python 执行文件同目录下

# bar.py

def baz():
    print('baz is being called.')

baz()

使用 import 导入这个模块时,baz 函数被调用了

import bar
# baz is being called.

This is not exactly what we want. 得使用 if __name__ == '__main__:',就称心如意了

import bar

bar.baz()
# baz is being called.

进一步,使用 main 函数符合编程的传统

在这里插入图片描述

3.1.2 doc

与函数文档类似,在开头使用成堆的三个连续双引号写一些内容,作为模块的文档,在调用时可以以 模块名.__doc__ 查看内容

在这里插入图片描述如上 profile 库

import profile

print(profile.__doc__)
# Class for profiling Python code.

3.1.3 all

  • 若未在模块中编写 __all__ 列表,那么 from 模块名 import * (但也别这么导入)将导入所有 不以下划线开头的 变量、函数、类;

  • 若在模块中编写了 __all__ 列表,那么在 from 模块名 import * 时,会导入名字属于 __all__ 列表元素的变量、函数、类。

在这里插入图片描述

导入模块后可以使用 模块名.__all__ 查看该属性

import profile

print(profile.__all__)
# ['run', 'runctx', 'Profile']

3.2 创建包

将相关的模块放进一个目录,并在目录下创建一个 __init__.py 的文件。

在执行文件的同目录下创建名为 foo 的包,包含 bar 模块

在这里插入图片描述就可以导入使用了

import foo

foo.bar.baz()
# baz is being called.

3.2.1 init 文件

文件夹中的 __init__.py 是 Python 的标识,应尽量保持简单。通常,除了必要的信息和 __all__ 放在 __init__.py,其他内容都放到模块文件中编写。

4. 搜索路径

当使用 import 导入模块或包时,Python 将按以下优先级查找

  1. 内存(在执行文件中已导入过的)
import foo

foo.bar.baz()
# baz is being called.

# 接着,将 foo 包删除

import foo

foo.bar.baz()
# baz is being called.

可见,若程序未终止,那么在本次运行中 import foo 仍然可行,因为 foo 包已加载入内存中。


  1. sys.path 包含的路径

在 anaconda 默认环境(base)下,模块的搜索路径可由 sys.path 查看,按照其中的路径由前向后依此查找。

import sys

sys.path
# ['',
# '/Users/xxx/data',
# '/anaconda3/lib/python37.zip',
# '/anaconda3/lib/python3.7',
# '/anaconda3/lib/python3.7/lib-dynload',
# '/anaconda3/lib/python3.7/site-packages',
# '/anaconda3/lib/python3.7/site-packages/aeosa',
# '/anaconda3/lib/python3.7/site-packages/IPython/extensions',
# '/Users/xxx/.ipython']
  • 第一个路径 '' 表示 .py 执行文件所在的目录;
  • 内置模块在 '/anaconda3/lib/python3.7'
  • 下载的包在 '/anaconda3/lib/python3.7/site-packages'
  • 若需要将不在该文件夹内的模块导入,则需要将模块的路径添加到 sys.path 之中 sys.path.append(new_path)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值