Python 进阶_模块 & 包

简介: 目录目录模块的搜索路径和路径搜索搜索路径命名空间和变量作用域的比较变量名的查找覆盖导入模块import 语句from-import 语句扩展的 import 语句 as自动载入模块模块导入的特性模块内建函数__import__...

目录

模块的搜索路径和路径搜索

搜索路径

默认的模块搜索路径在 Python 解析器编译安装时被指定, 我们可以通过 sys 模块来查看和修改它:

In [4]: sys.path
Out[4]: 
['',
 '/usr/bin',
 '/usr/lib/python2.7',
 '/usr/lib/python2.7/plat-x86_64-linux-gnu',
 '/usr/lib/python2.7/lib-tk',
 '/usr/lib/python2.7/lib-old',
 '/usr/lib/python2.7/lib-dynload',
 '/usr/local/lib/python2.7/dist-packages',
 '/opt/stack/keystone',
 '/opt/stack/glance',
 '/opt/stack/cinder',
 '/opt/stack/nova',
 '/opt/stack/horizon',
 '/opt/stack/tempest',
 '/opt/stack/oslo.vmware',
 '/usr/lib/python2.7/dist-packages',
 '/usr/lib/python2.7/dist-packages/IPython/extensions']

存在于搜索路径列表的路径下的模块就可以直接被 import 了.
我们还能够通过 sys.models 可以找到当前导入了那些模块和它来自萨满路径和地方.
NOTE: 这个路径每个人都不尽相同, 在安装 Openstack 项目时, 每一个项目的根目录都会加入到该目录列表中

命名空间和变量作用域的比较

命名空间: 是变量名(标识符)到实际对象的映射, 是一个字典. Python 的命名空间类型有 内建命名空间/全局命名空间/嵌套命名空间/局部命名空间.
Python 解析器启动时, 首先会加载 内建命名空间 , 该空间的变量名映射被包含在 __builtin__ 模块中, 我们可以通过 __builtin__.__dict__ 来查看其包含的变量字典, 主要包含了 ERROR/内建函数 等类型.

注意: __builtin__ 模块和 __builtins__ 模块的名称非常相似, 在标准的 Python 环境中 __builtins__ 含有 __builtin__ 内的所有变量名映射, 却别在于 __builtins__ 是可以被修改的, 用于创建一个 “沙盒” 环境, 但少有人用, 所以两者并不相等.

作用域: 变量名有效的区域定义. 指定了一个变量名在一个指定的区域内有效.

两者的区别: 作用域和命名空间非常相似, 一个作用域的创建伴随着新的命名空间的生成, 其一般是具有对应的关系. 所以往往命名空间中含有的变量名在对应的作用域中都是有效的. 但本质的区别是: 命名空间是纯粹意义上的变量名和对象的映射关系, 而作用域还指出了在代码中的那个物理位置(模块内/类内/函数类)可以访问到命名空间的变量名, 从而得到其映射的对象.

无限制的命名空间: Python 的一个特性在于我们可以动态的为一个函数对象添加变量, 这种变量也称之为实例属性. 所以 Python 的命名空间是无限制的.

In [9]: def func():
   ...:     print "This is a func"
   ...:     

In [10]: func.__dict__
Out[10]: {}

In [13]: func.name = 'JMilkFan'

In [14]: func.__dict__
Out[14]: {'name': 'JMilkFan'}

变量名的查找/覆盖

当我们 call 一个变量名时, Python 解析器的查找顺序如下:
1. 先从局部命名空间开始找, 如果找到了, 则引用变量名映射的对象. 若没有找到, 则进行下一步
2. 到嵌套命名空间找, 如果没有找到, 则进行下一步
3. 到全局命名空间找, 如果没有找到, 则进行下一步
4. 到内置命名空间找, 如果没有找到, 则进入下一步

从这个变量名查找算法可以看出, 当我们在代码物理位置定义了一个变量时, 这个变量就会添加到命名空间中. 而且这个命名空间为变量名的查找提供了清单. 更重要的一点是这个查找算法还有效的覆盖了外层作用域的同名变量. 局部作用域 覆盖 嵌套作用域 覆盖 全局作用域 覆盖 内置作用域.

导入模块

import 语句

import module1[, module2, ..., moduleN]

Python 允许一行导入多个模块, 但那这并不符合 PEP8 的编程标准, 所以建议使用多行导入的方式.

导入模块类型的顺序(中间已单空行隔开):
1. Python 标准库模块
2. Python 第三方模块
3. Python 自定义模块

NOTE: 模块的导入遵循作用域的原则, 在顶格导入的模块, 那么模块的作用域是全局的. 在函数或类内导入的模块, 其作用域就是局部或嵌套作用域.

from-import 语句

如果你希望从一个模块中导入指定属性, 或希望从一个 package 中导入一个模块, 都可以使用 form-import 语句.

from-import 语句也支持一行导入多个模块或属性, EG.

from package import (module1, module2, module3, ..., moduleN)

from-import 语句的好处在于: 针对性的导入可以提高效率和节省空间

NOTE: 我们一般建议导入到模块即可, 非特殊情况不要导入包或模块内的属性

扩展的 import 语句 as

也称之为别名, 模块之间也会经常出现同名的情况, 如果出现同一个模块中导入了两个或多个同名模块的情况, 那么应该为每个相同的模块取一个别名来有效区分. 除此之外, 如果模块的全称过长, 我们也可以为其取一个短小的别名. EG.

import module1 as module_one

from package import module1 as module_two

import Tkinter as tk

自动载入模块

Python 解析器在标准模式下启动会自动的导入一个模块, 例如 __bulitin__. 我们可以通过 sys.modules 来查看已经被导入到当前环境下模块字典, key 为模块名, value 为模块路径.

import sys
sys.modules.keys()

模块导入的特性

  • 加载模块时执行文件
    在导入模块时, 其顶格的代码(全局变量/类定义/函数定义…)会被执行, 所以不建议写太多的顶格代码, 应尽量多的将顶格代码收入函数或类体内.

  • 导入和加载模块是不一样的
    一个模块可以被导入多次, 但正常情况下只能被加载一次. 当然除了手动加载之外. EG: 你需要在一个模块中导入 5 个模块, 其中之一为 sys 模块, 然后另外的 4 个模块也需要导入 sys 模块, 这种情况下, sys 模块只会被加载一次, 但却会被导入 5 次.

  • 导入到当前命名空间的变量
    通过 from-import 导入到当前命名空间的模块变量是不需要通过句点标识符来调用的, 直接就可以引用. 但是不建议通过 from-import 来直接导入模块变量, 这样容易污染当前的命名空间, 可能导致覆盖一个已经存在的具有相同名字的对象.

模块内建函数

__import__()

格式:

__import__(module_name[, globals[, locals[, fromlist]]])
# globals 是全局命名空间的字典 ⇒ globals()
# locals 是局部命名空间的字典 ⇒ locals()
# fromlist 是 from-import 语句导入的变量名的列表 ⇒ []

当我们执行 import 语句的时候, 实际上是调用了 __import__() 内置函数, EG:

import sys 
# 等效于
sys = __import__('sys')

globals() / locals() / reload()

  • globals(): 返回调用者的全局命名空间的字典
  • locals(): 返回调用者的局部命名空间的字典
    NOTE: 如果在全局命名空间调用上面两个内置函数, 那么两者返回的字典是相同的

  • reload(): 重新导入一个已经被导入了的模块
    NOTE: reload() 由两个使用限制

    1. 模块必须全部被导入, 不能重载通过 from-import 来导入模块属性的模块
    2. 该模块必须是已经被导入了的, 才能被重载
      模块的顶格代码在导入的时候会执行且仅执行一次, 再次导入的时候不会被执行, 如果希望再次执行的话, 可以使用 reload()

Package 包

模块是代码的组织形式, 包是模块的组织形式. 如果在一个目录中创建了 __init__.py 文件, 那么 Python 解析器会将该目录标识为一个包 Package.
NOTE: 我们一般在使用 import 语句的时候, 建议导入到模块级别, 不要导入模块属性, 也不要导入包.

__init__.py

__init__.py 文件是包的标识文件, 作为包的初始化模块, from-import 包下的模块会子包时, 需要用到该初始化模块, 所以现在如果一个包中没有该模块时, 会触发 ImportWarning 信息.

import package

如果我们不需要使用初始化模块__init__.py时. 该模块的内容为空, 如果我们需要使用该模块时, import packageName == import packageName._init_.
而且需要注意的是: 如果我们执行 from package import * 时, 会将该包下的所有模块和属性导入, 实际上这种做法是不科学的. 所以在包的初始化模块文件中有一个特殊属性 __all__ , __all__ 属性由一个模块名字组成的列表组成, 这个列表中包含了所有在执行全导入时应该被导入的模块和属性的名字.

相关文章
|
30天前
|
SQL 关系型数据库 数据库
Python SQLAlchemy模块:从入门到实战的数据库操作指南
免费提供Python+PyCharm编程环境,结合SQLAlchemy ORM框架详解数据库开发。涵盖连接配置、模型定义、CRUD操作、事务控制及Alembic迁移工具,以电商订单系统为例,深入讲解高并发场景下的性能优化与最佳实践,助你高效构建数据驱动应用。
253 7
|
1月前
|
监控 安全 程序员
Python日志模块配置:从print到logging的优雅升级指南
从 `print` 到 `logging` 是 Python 开发的必经之路。`print` 调试简单却难维护,日志混乱、无法分级、缺乏上下文;而 `logging` 支持级别控制、多输出、结构化记录,助力项目可维护性升级。本文详解痛点、优势、迁移方案与最佳实践,助你构建专业日志系统,让程序“有记忆”。
209 0
|
1月前
|
JSON 算法 API
Python中的json模块:从基础到进阶的实用指南
本文深入解析Python内置json模块的使用,涵盖序列化与反序列化核心函数、参数配置、中文处理、自定义对象转换及异常处理,并介绍性能优化与第三方库扩展,助你高效实现JSON数据交互。(238字)
280 4
|
1月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
214 0
|
1月前
|
XML JSON 数据处理
超越JSON:Python结构化数据处理模块全解析
本文深入解析Python中12个核心数据处理模块,涵盖csv、pandas、pickle、shelve、struct、configparser、xml、numpy、array、sqlite3和msgpack,覆盖表格处理、序列化、配置管理、科学计算等六大场景,结合真实案例与决策树,助你高效应对各类数据挑战。(238字)
157 0
|
2月前
|
安全 大数据 程序员
Python operator模块的methodcaller:一行代码搞定对象方法调用的黑科技
`operator.methodcaller`是Python中处理对象方法调用的高效工具,替代冗长Lambda,提升代码可读性与性能。适用于数据过滤、排序、转换等场景,支持参数传递与链式调用,是函数式编程的隐藏利器。
114 4
|
10月前
|
存储 人工智能 运维
【01】做一个精美的打飞机小游戏,浅尝阿里云通义灵码python小游戏开发AI编程-之飞机大战小游戏上手实践-优雅草央千澈-用ai开发小游戏尝试-分享源代码和游戏包
【01】做一个精美的打飞机小游戏,浅尝阿里云通义灵码python小游戏开发AI编程-之飞机大战小游戏上手实践-优雅草央千澈-用ai开发小游戏尝试-分享源代码和游戏包
554 48
【01】做一个精美的打飞机小游戏,浅尝阿里云通义灵码python小游戏开发AI编程-之飞机大战小游戏上手实践-优雅草央千澈-用ai开发小游戏尝试-分享源代码和游戏包
|
2月前
|
存储 数据库 开发者
Python SQLite模块:轻量级数据库的实战指南
本文深入讲解Python内置sqlite3模块的实战应用,涵盖数据库连接、CRUD操作、事务管理、性能优化及高级特性,结合完整案例,助你快速掌握SQLite在小型项目中的高效使用,是Python开发者必备的轻量级数据库指南。
267 0
|
3月前
|
数据处理 开发工具 开发者
requirement.txt 管理python包依赖
在 Python 项目中,`requirements.txt` 用于记录依赖库及其版本,便于环境复现。本文介绍了多种生成该文件的方法:基础方法使用 `pip freeze`,进阶方法使用 `pipreqs`,专业方法使用 `poetry` 或 `pipenv`,以及手动维护方式。每种方法适用不同场景,涵盖从简单导出到复杂依赖管理,并提供常见问题的解决方案,帮助开发者高效生成精准的依赖列表,确保项目环境一致性。
1082 4
|
3月前
|
存储 安全 数据处理
Python 内置模块 collections 详解
`collections` 是 Python 内置模块,提供多种高效数据类型,如 `namedtuple`、`deque`、`Counter` 等,帮助开发者优化数据处理流程,提升代码可读性与性能,适用于复杂数据结构管理与高效操作场景。
312 0

推荐镜像

更多