基础
逻辑组织和物理组织
- 逻辑组织是模块,module
- 物理组织是文件,file
- 文件名=模块名.py
- 导入的是模块或模块属性
默认搜索路径
- 环境变量,PYTHONPATH
- 脚本(解释器)启动后,也可以使用,sys.path (list)查看;
- 使用sys.path.append(r’/var/opt/lib’)添加新的路径到末尾
- 使用sys.path.insert()到指定位置
- 使用sys.modules(dict)查看当前导入的模块,以及相应的位置
- sys.modules().keys()
名称空间
- 名称空间是名字和对象之间的映射关系
- 作用域是用户代码哪些物理位置可以访问到这些名字
- module.name,保证了不同module可以共用相同的函数,变量名称
- 内建名称空间,全局名称空间,局部名称空间,局部名称空间是不断变化的,所以执行期间有2-3个活动的名称空间
- Python解释器首先加载内建名称空间(__buildins__),随后加载执行模块的全局名称空间,上述会在模块开始执行后变为活动名称空间
- 调用globals()查看全局变量
- 调用locals()查看局部变量
名称空间和作用域的含义,名称空间纯粹意义上就是一个变量名字到对象之间的映射字典,python和c,c++等语言不通,对于C来说,变量名字实际上是内存地址别名,对于python来说,名字就是名字,是通过名称空间建立到和对象的映射关系,改变一个名字实际上是重新绑定到其他对象,删除一个名字是解除和对象的绑定;
作用域的含义是代码执行到哪些物理位置可以访问到这些名字,是否可以看得到这个变量名字。
当访问一个名字的时候,解释器就会做名称查询,从局部名称空间,一层一层向上查找到内建名称空间,失败了就返回错误,这里面隐含着一件事,就是内层空间会覆盖外层空间,在局部空间找到了,就不会再向上查找了,相当于覆盖了全局变量,找到了之后会把变量加到局部名称空间中,初始值用外面的,但是赋值之后不会修改到外面的值。
无限制名称空间
def func():
pass
func.__doc__='dfs'
func.version=2.0
class a:
pass
a.x=9
a,y=10
导入模块
import os
import urllib
import mymodule
from module import classA, func, gName
from module import (A,B..)
import module as NameModule
from module import classA as classB
- 导入模块时,解释器会在默认搜索路径中寻找,找到了就会加载它,该过程遵循作用域原则,如果在本文件的顶层导入,就是导入模块的作用于就是全局的,如果在函数中导入,导入模块的作用域就局部的。
- 模块第一次导入的时候,会被加载执行,即所有顶层代码都会被执行!包括全局变量以及类和函数的声明,如果有检查name的操作,也会执行。
- 一个模块只被加载一次,无论被导入了多少次,这可以阻止多重导入时代码被多次执行
- from module import var 可以把var导入当前的名称空间,这意味着不需要module.var,直接使用var就能访问
- from module import var导入的时候,var会在局部名称空间,如果直接使用var的话,给它重新赋值的时候,不会影响被被导入模块module.var的值,只会改变本模块局部变量var,如果要改变被导入模块的值,需要使用module.var的方式赋值
- 这里也引出了一个问题,跨模块的全局变量访问,要想要大家都直接去修改,就要用module.A来访问,还有个更好的办法是,共享的模块使用函数来访问。
g_lsName = ""
def set_g_lsName(sName)
global g_lsName
g_lsName = sNname
return
del get_g_lsName()
global g_lsName
return g_lsName
__import__方法
- 实际导入模块的方法,提供这个函数是为了特殊需求的用户可以覆盖它,实现自定义导入算法
__import__(modulename, globals=globals(), locals=locals(), fromlist=[])
sys = __import__('sys')
reload()方法
- 重新导入一个已经导入的模块
- 参数是模块名字本身,而不是字符串
- reload(os) not reload(‘os’)
- 模块导入的时候执加载一次,后续的import就不会再加载了,但是执行reload()可以重新加载
包
- 包是有层级结构的,对应文件的目录结构
- 包定义了一个由模块和子包组成的python应用程序执行环境
- 和类,模块一样,包也使用.来访问元素
- 每层目录下必须要有init.py文件,这是初始化模块,在from-import语句导入子包的时候需要使用它
import dirA.dirB.moduleA
dirA.dirB.moduleA.func()
from dirA.dirB import dirC
dirC.moduleA.func()
from dirA.dirB.dirC import func
func()
绝对导入和相对导入
- 相对导入容易覆盖内建模块,现在的导入必须是绝对路径导入,这些名字必须通过Python路径即sys.path或是PYTHONPATH来访问
- 允许报包名前置句点实现相对导入
from .dirB import module
from ..dirA import module
Reference
Python核心编程
http://shomy.top/2016/03/01/python-namespace-1/