当前位置: 首页 > news >正文

Python - 模块

目录

  • 1. 概述
  • 2. 模块名称空间
  • 3. 搜索路径和路径搜索
  • 4. 名称空间
    • 名称空间与变量作用域比较
    • 名称查找, 确定作用域, 覆盖
  • 5. 无限制的名称空间
  • [参考文献]

1. 概述

模块支持从逻辑上组织Python代码。当代码量变得相当大的时候,最好把代码分成一些有组织的代码段,前提是保证它们的彼此交互。那些自我包含并且有组织的代码片段就是模块(module)。

2. 模块名称空间

从基本概念来说, 一个名称空间就是一个从名称到对象的关系映射集合。给定一个模块名之后, 只可能有一个模块被导入到 Python 解释器中。在不同模块间不会出现名称交叉现象,每个模块都定义了它自己的唯一的名称空间。

3. 搜索路径和路径搜索

模块的导入需要一个叫做"路径搜索"的过程。即在文件系统"预定义区域"中查找 *.py 文件。这些预定义区域只是你的 Python 搜索路径的集合。路径搜索和搜索路径是两个不同的概念,前者是查找某个文件的操作,后者是去查找一组目录。有时候导入模块操作会失败:

 >>> import xxx
     Traceback (innermost last):
     File "<interactive input>", line 1, in ?
     ImportError: No module named xxx

发生这样的错误时, 解释器会告诉你它无法访问请求的模块,可能的原因是模块不在搜索路径里, 从而导致了路径搜索的失败。
默认搜索路径是在编译或是安装时指定的。它可以在一个或两个地方修改。
启动 Python 的 shell 或命令行的 PYTHONPATH 环境变量。该变量的内容是一组用冒号分割的目录路径。如果你想让解释器使用这个变量, 那么请确保在启动解释器或执行 Python 脚本前设置或修改了该变量。 解释器启动之后, 也可以访问这个搜索路径, 它会被保存在 sys 模块的 sys.path 变量里。不过它已经不是冒号分割的字符串, 而是包含每个独立路径的列表。切记, 搜索路径在不同系统下一般是不同的

>>> sys.path
['', '/usr/lib64/python27.zip', '/usr/lib64/python2.7', '/usr/lib64/python2.7/plat-linux2', '/usr/lib64/python2.7/lib-tk', '/usr/lib64/python2.7/lib-old', '/usr/lib64/python2.7/lib-dynload', '/usr/lib64/python2.7/site-packages', '/usr/lib/python2.7/site-packages']

sys.path 变量只是个列表, 所以我们可以随时随地对它进行修改。如果某个模块不在搜索路径里,那么只需要调用列表的 append() 方法即可。

sys.path.append('/home/wesc/py/lib')

某个模块有可能有很多拷贝。这时,解释器会沿用路径搜索顺序找到的第一个模块。
使用 sys.modules 可以找到当前导入了哪些模块和它们来自什么地方。和sys.path 不同, sys.modules 是一个字典, 使用模块名作为键( key),对应物理地址作为值( value )。

4. 名称空间

名称空间是名称(标识符)到对象的映射。向名称空间添加名称的操作过程涉及到绑定标识符到指定对象的操作(以及给该对象的引用计数加 1 )。 Python 的名称(Name)是对象的一个标识(Identifier)。在Python里面一切皆对象,名称就是用来引用对象的。
执行期间会有两个或三个活动的名称空间。这三个名称空间分别是局部名称空间,全局名称空间和内建名称空间。但局部名称空间在执行期间是不断变化的, 所以我们说"两个或三个"。
Python 解释器首先加载内建名称空间。 它由__builtins__模块中的名字构成。 随后加载执行模块的全局名称空间, 它会在模块开始执行后变为活动名称空间。这样我们就有了两个活动的名称空间。

__builtins__模块和__builtin__模块不能混淆。__builtins__模块包含内建名称空间中内建名字的集合。其中大多数来自__builtin__模块,该模块包含内建函数,异常以及其他属性。

如果在执行期间调用了一个函数, 那么将创建出第三个名称空间,即局部名称空间。 我们可以通过 globals() 和 locals()内建函数判断出某一名字属于哪个名称空间。

名称空间与变量作用域比较

名称空间是纯粹意义上的名字和对象间的映射关系,而作用域还指出了从用户代码的哪些物理位置可以访问到这些名字。

611089-20190728150622152-1137587529.png

注意每个名称空间是一个自我包含的单元。但从作用域的观点来看, 事情是不同的. 所有局部名称空间的名称都在局部作用范围内。局部作用范围以外的所有名称都在全局作用范围内。还要记得在程序执行过程中,局部名称空间和作用域会随函数调用而不断变化, 而全局名称空间是不变的。

名称查找, 确定作用域, 覆盖

那么确定作用域的规则是如何联系到名称空间的呢? 它所要做的就是名称查询. 访问一个属性时, 解释器必须在三个名称空间中的一个找到它。 首先从局部名称空间开始, 如果没有找到, 解释器将继续查找全局名称空间. 如果这也失败了, 它将在内建名称空间里查找。 如果最后的尝试也失败了, 你会得到错误 :

>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined

这个错误体现了,先查找的名称空间是如何“屏蔽”其他后搜索的名称空间的。这体现了名称覆盖的影响。上面图中的灰盒子展示了遮蔽效应。例如,局部名称空间中找到的名字会隐藏全局或内建名称空间的对应对象。这就相当于“覆盖”了那个全局变量。例如:

def foo():
    bar = 200
    print("in foo,bar is",bar)
    
bar = 100
print("in main,bar is",bar)
foo()

输出结果:
in main,bar is 100
in foo,bar is 200

foo()函数局部名称空间里的bar变量覆盖了全局的bar变量。虽然bar存在域全局名称空间里,但程序首先找到的是局部名称空间里的那个,所以覆盖了全局的那一个。

5. 无限制的名称空间

Python 的一个有用的特性在于你可以在任何需要放置数据的地方获得一个名称空间。比如,可以在任何时候给函数添加属性。

def foo():
    pass
foo.__doc__ = 'doc.'
foo.version = 0.2

你可以把任何想要的东西放入一个名称空间里。

[参考文献]

  1. 《Python 核心编程(第二版)》
  2. Python 名称空间与作用域 https://blog.csdn.net/lihao21/article/details/79112054

转载于:https://www.cnblogs.com/sxiszero/p/11259056.html

相关文章:

  • 【评论】Lisp天才神话
  • 近期橡胶抓大放小的过程与思路 (2018-08-22 18:32:59)
  • 云计算与虚拟化之后:网络威胁成新挑战
  • Redux学习总结
  • js如何隐藏表格的行与列
  • spring整合LOG4J2日志
  • redis 详细讲解
  • 安装SQL-SERVER提示重启计算机
  • C++学习笔记-2-数组
  • 强化VB.NET编程多线程句柄技巧(转载)
  • Ansible 自动化运维部署
  • IdHTTP处理HTTP 302遇到的问题
  • 如何进行数据库,比如ORACLE,SQL SERVER的逆向工程,将数据库导入到PowerDesigner中...
  • 微软首次针对Windows 7推杀毒软件 年内将推出
  • leetcode-02 两数相加
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 77. Combinations
  • eclipse(luna)创建web工程
  • es6--symbol
  • maya建模与骨骼动画快速实现人工鱼
  • PHP 的 SAPI 是个什么东西
  • redis学习笔记(三):列表、集合、有序集合
  • Vue小说阅读器(仿追书神器)
  • Webpack 4x 之路 ( 四 )
  • 当SetTimeout遇到了字符串
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 工程优化暨babel升级小记
  • 嵌入式文件系统
  • 人脸识别最新开发经验demo
  • 使用agvtool更改app version/build
  • 用简单代码看卷积组块发展
  • 最近的计划
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • #162 (Div. 2)
  • (10)ATF MMU转换表
  • (6)STL算法之转换
  • (Note)C++中的继承方式
  • (笔试题)合法字符串
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)http协议
  • .chm格式文件如何阅读
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • [\u4e00-\u9fa5] //匹配中文字符
  • [100天算法】-x 的平方根(day 61)
  • [145] 二叉树的后序遍历 js
  • [20170705]lsnrctl status LISTENER_SCAN1
  • [8481302]博弈论 斯坦福game theory stanford week 1
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • [AIGC] 如何建立和优化你的工作流?
  • [android]-如何在向服务器发送request时附加已保存的cookie数据
  • [Arduino学习] ESP8266读取DHT11数字温湿度传感器数据