python核心编程--第十二章

故事扮演 提交于 2020-04-07 05:04:57

12.2 模块和文件

如果说模块是按照逻辑来组织 Python 代码的方法, 那么文件便是物理层上组织模块的方法。因此, 一个文件被看作是一个独立模块, 一个模块也可以被看作是一个文件。 模块的文件名就是模块的名字加上扩展名 .py 。

当我们要导入模块的时候,需要知道模块放在相应的路径下才行。

>>> import sys
>>> sys.path
['C:\\Python27\\Lib\\idlelib', 'C:\\Windows\\system32\\python27.zip', 'C:\\Python27\\DLLs', 'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\\Python27\\lib\\lib-tk', 'C:\\Python27', 'C:\\Python27\\lib\\site-packages', 'C:\\Python27\\lib\\site-packages\\PIL', 'C:\\Python27\\lib\\site-packages\\win32', 'C:\\Python27\\lib\\site-packages\\win32\\lib', 'C:\\Python27\\lib\\site-packages\\Pythonwin', 'C:\\Python27\\lib\\site-packages\\wx-2.8-msw-ansi']
所以,你可以直接执行程序将新的路径添加进去即可。
sys.path.append('/home/wesc/py/lib')
使用 sys.modules 可以找到当前导入了哪些模块和它们来自什么地方。 和 sys.path 不同,sys.modules 是一个字典, 使用模块名作为键( key) , 对应物理地址作为值( value )

12.3 名称空间

名称空间是名称(标识符)到对象的映射。 向名称空间添加名称的操作过程涉及到绑定标识符到指定对象的操作(以及给该对象的引用计数加 1 )。 《Python 语言参考》(Python Language Reference)有如下的定义: 改变一个名字的绑定叫做重新绑定, 删除一个名字叫做解除绑定。

Python 解释器首先加载内建名称空间。 它由 __builtins__ 模块中的名字构成。 随后加载执行模块的全局名称空间, 它会在模块开始执行后变为活动名称空间。 这样我们就有了两个活动的名称空间。

核心笔记: __builtins__ 和 __builtin__
__builtins__ 模块和 __builtin__ 模块不能混淆。 虽然它们的名字相似——尤其对于新手来说。 __builtins__ 模块包含内建名称空间中内建名字的集合。 其中大多数(如果不是全部的话)来自 __builtin__ 模块, 该模块包含内建函数, 异常以及其他属性。 在标准 Python 执行环境下,__builtins__ 包含 __builtin__ 的所有名字。 Python 曾经有一个限制执行模式, 允许你修改__builtins__ , 只保留来自 __builtin__ 的一部分, 创建一个沙盒(sandbox)环境。但是, 因为它有一定的安全缺陷, 而且修复它很困难, Python 已经不再支持限制执行模式。(如版本2.3 )

但是,我发现:

>>> __builtin__

Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    __builtin__
NameError: name '__builtin__' is not defined
如果在执行期间调用了一个函数, 那么将创建出第三个名称空间, 即局部名称空间。 我们可以通过 globals() 和 locals() 内建函数判断出某一名字属于哪个名称空间。

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

下图展示了名称空间和变量作用域的关系:

注意每个名称空间是一个自我包含的单元。但从作用域的观点来看, 事情是不同的. 所有局部名称空间的名称都在局部作用范围内。局部作用范围以外的所有名称都在全局作用范围内。

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

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

>>> foo

Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    foo
NameError: name 'foo' is not defined
这里要注意一点:局部名称会覆盖全局,而全局会覆盖内建。

12.3.3 无限制的名称空间

class oneClass(object):
    pass
bar = oneClass()
bar.x = 100
bar.y = 200
bar.version = 0.1
bar.completed = False

print bar.x, bar.y, bar.version, bar.completed
程序输出:
>>> 
100 200 0.1 False
当然,如果你这样写的话,会出错的:
class oneClass(object):
    pass
bar = oneClass()
bar.x = 100
bar.y = 200
bar.version = 0.1
bar.completed = False

print bar.x, bar.y, bar.version, bar.completed

new_bar = oneClass()
print new_bar.x
程序异常:
>>> 
100 200 0.1 False

Traceback (most recent call last):
  File "C:\Python27\hello.py", line 12, in <module>
    print new_bar.x
AttributeError: 'oneClass' object has no attribute 'x'
你可以把任何想要的东西放入一个名称空间里。
说实在的看到这里我吓了一跳。熟悉的C++里面对封装的严谨性要求很高,但是python居然允许把想要的任何东西放进一个名词空间中。

当然,思考了一下这样做的好处就是:灵活了类的设计!!!


核心风格: import 语句的模块顺序
我们推荐所有的模块在 Python 模块的开头部分导入。 而且最好按照这样的顺序:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!