模块、包、命名空间和作用域

    技术2022-07-11  81

    模块

    模块是python中的最高组织单元,在物理层面上,模块以文件存储,模块的文件名就是模块的名字.py,每个模块都有自己的名称空间。 python按照路径搜索来查找模块文件,在PYTHONPATH环境变量中的路径为Python模块的搜索路径,通过sys.path属性可以看到模块搜索路径的列表,python按照这个列表的顺序对模块进行搜索,所以在路径列表前面的路径搜索到模块之后就不会继续搜索。由于该值是一个列表,可以通过sys.path.append方法,或者sys.path.insert方法添加路径到该列表中,或者通过sys.path.pop方法将某些路径排除到搜索路径之外等等。

    模块的物理层面是文件,包就是有层次的特殊文件结构,特殊的点在于,每个目录下面都必须有__init__.py文件,如果没有该文件,则只是一个普通的文件目录,并不能作为包导入。这是因为导入包的原理其实就是导入该包的路径下面的__init__.py,其中包含可以导入的各种模块。

    模块导入和加载

    浅谈python模块的导入操作 import语句导入指定的模块时会执行三个步骤: 1.在指定路径下搜索模块文件,找到模块文件 2.指定的模块在被导入时就会被编译成字节码,即编译成.pyc文件 3.依靠模块的代码中的定义来创建其所定义的对象,模块文件中的所的语 句会依次执行,从头至尾,而此步骤中任何对变量名的赋值运算,都会产生所得到的模块文件的属性 但是请注意:模块只在第一次导入时才会执行如上步骤,后续的导入操作只不过是提取内存中已加载的模块对象 可以使用reload()命令重新加载指定的模块

    通过import、from import语句导入一个模块,或者通过as给模块起别名,模块只有在第一次导入的时候才会被加载,模块加载时,其实就是执行模块中的所有语句,此时,如果模块中除了定义的类和方法之外,在全局作用域下有代码时,这些代码会被执行,所以在模块编写中需要避免在顶级作用域下直接执行代码。

    # a.py print 'm' def f(): print 'fm' class A(object): print 'A.m' def fa(self): print 'A.f.m' # b.py import a

    从b模块中导入a,运行b,会输出:

    m A.m

    模块中的顶层变量会在模块导入时就执行,类的类变量也是如此,因此在模块中应该尽量避免这种,放在函数中进行延迟生成。这里需要深入了解模块的导入机制。 在模块第一次被导入时,往往会比较慢,这是因为python在导入一个新的模块时,会从模块所在目录检查是否有.pyc文件,如果没有该文件,则会将模块编译成字节码,从而提高下一次导入的效率*。 python也可以从一个ZIP文件中导入模块,该ZIP文件会被看成一个包,然而python不会再生成.pyc文件到该ZIP文件中,所以导入效率相对较低一些。

    命名空间

    命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。一般有三种命名空间:局部名称空间、全局名称空间、内建名称空间。内建名称空间的所有名字都包含在__builtins__模块中,该模块又包含__buitin__模块,该模块中包含内建函数、异常以及其他属性,每一个python程序执行之前都会先导入__builtins__模块,每个模块都有自己的名称空间,导入一个模块时,会加载执行模块的全局名称空间,这也是为什么在加载一个模块时,所有全局作用域下的代码会直接执行。 在访问一个属性的时候,会从局部名称空间、全局名称空间、内建名称空间中寻找该名字,如果都找不到则会返回一个NameError的错误,由于寻找时总是先去寻找局部名称空间,所以局部名称空间中如果有和全局名称空间中的变量重名,则会讲全局名称空间中的变量被“覆盖”*(其实是不会再被找到)。

    命名空间和作用域的关系

    Python3 命名空间和作用域 变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。 Python变量作用域可以分为四种,分别为局部作用域、嵌套作用域、全局作用域、内置作用域。

    所有局部名称空间的名称都在局部作用范围内,局部名称空间之外的所有名称都在全局作用范围内。局部名称空间和作用域会随着函数的调用而不断变化,但是全局名称空间是不变的。名称空间决定一个变量名字是否存在,而作用域决定一个变量名字是否可以被访问到。通过globals()、locals()内建函数可以判断出某一名字属于哪个名称空间。

    Processed: 0.017, SQL: 9