Python的import语句(Win10)

Python的import语句,作用是将模块或包导入当前程序中。

import语句的语法结构定义(文法规则)如下:

   import_stmt     ::= "import" module ["as" identifier] ("," module ["as" identifier])*

                   | "from" relative_module "import" identifier ["as" identifier]

                   ("," identifier ["as" identifier])*

                   | "from" relative_module "import" "(" identifier ["as" identifier]

                   ("," identifier ["as" identifier])* [","] ")"

                   | "from" relative_module "import" "*"

   module          ::= (identifier ".")* identifier

   relative_module ::= "."* module | "."+

看到这个语法结构定义及其使用的符号,个人感觉这是巴克斯范式和正则表达式的结合体。“::=”在巴克斯范式中可读作“定义为”;一条文法规则从形式上看是由“::=”连接的左右两个部分,“::=”左侧的符号称作非终结符(计算机基础学科——编译原理中的术语),就是在程序代码中不会出现的符号;“::=”右侧的符号串由一个或多个终结符和非终结符组成。编译器或解释器(Python是解释型语言,对程序解释执行)按照文法规则对程序代码进行理解并执行(编译或解释)。

上述import语句语句的文法定义中,“::=”右侧的符号串中,双引号中的符号串(字符或字符串)是在源代码中出现的关键字;中括号、小括号、以及星号是正则表达式中使用非符号。

上述语句的文法定义可从命令行获取,也可从帮助文档得到。

命令行获取方式,在命令行依次键入如下命令:

python

help()

import

 在帮助文档中,查看的路径是:“The Python Language Reference”->“Simple statements”->“The import statement”。

为了加深印象,将上述英文部分翻译为中文。个人感觉理解这些帮助文档还是需要有一定的理论和实践基础的,翻译过程中有不少困难需要克服。需要对操作系统、编译原理、数据结构等有一定的了解:用户要求操作系统执行Python程序,操作系统按Python程序的要求创建Python进程,Python进程(类似于与现实社会中的组织、机构)中有一个至关重要的名为Python解释器的存在,Python解释器完成对用户输入的命令或程序的解释执行,使用了一个名为名空间(namespace)的数据结构。

以下为译文(译文中动词的执行者应该是Python解释器)。水平有限,仅供参考

基本的import语句(没有from子句)分两步执行:

  1. 查找一个模块,必要时加载该模块并进行初始化
  2. 在本地名空间的import语句的作用范围内定义一个或多个名称。

当语句包含多个子句(用逗号分隔)时,将为每个子句分别执行这两个步骤,就像这些子句已被分隔为单独的导入语句一样。

关于第一步(查找和加载模块)的更详细的描述可参见“import系统”(import system),“import系统”还描述了可导入的各种类型的包和模块,以及可用于定制导入系统的所有挂钩(hooks)。

请注意,若此步骤失败,则表示无法定位模块或者在初始化模块时发生错误(包括执行模块代码时发生的错误)。

如果成功检索到被请求的模块,将通过以下三种方式之一使得该模块在本地名空间中可用:

•如果模块名称后接as,则as后的名称将直接绑定到导入的模块。

•如果未指定其他名称,并且要导入的模块是顶级模块,则该模块的名称将绑定在本地命名空间中,作为被导入模块的引用。

•如果要导入的模块不是顶级模块,则包含该模块的顶级包的名称将绑定在本地命名空间中,作为对顶级包的引用。必须使用被导入的模块的完整限定名访问该模块,而不能直接访问。

对from结构的处理要复杂一些:

  1. 查找from子句中指定的模块,必要时加载并初始化;
  2. 对于import子句中指定的每个标识符:

(1)检查被导入的模块是否具有与标识符同名的属性;

(2)若没有,则尝试导入具有该名称的子模块,然后再次检查被导入的子模块的同名属性;

(3)如果未找到属性,则产生导入错误(ImportError)。

(4)如果找到,则将一个对该值的引用存储在本地命名空间中;引用名的确定规则是:如果存在as子句,则使用其中的名称,否则使用属性名称。

例子:

import foo                 # foo imported and bound locally (foo被导入,与本地名foo绑定)

import foo.bar.baz         # foo.bar.baz imported, foo bound locally (foo.bar.baz被导入,foo与本地名foo绑定)

import foo.bar.baz as fbb  # foo.bar.baz imported and bound as fbb (foo.bar.baz被导入,并与名fbb绑定)

from foo.bar import baz    # foo.bar.baz imported and bound as baz (foo.bar.baz被导入,与名baz绑定)

from foo import attr       # foo imported and foo.attr bound as attr (foo被导入,并将foo.attr与名attr绑定)

如果标识符列表被星号(“*”)替换,则模块中定义的所有公共名称都将绑定到import语句所在范围的本地命名空间中。

模块定义的公共名称是通过检查模块名称空间中名为__all__的变量来确定的,如果定义了该变量,则它必须是由该模块定义或导入的名称组成的字符串序列。__all__中给出的名称都被视为公共名称,并且必须存在。如果没有定义变量__all__,公共名称集包括在模块命名空间中找到的所有名称,这些名称以下划线字符开头('_')。__all__应包含所有的公共API。它旨在避免意外导出不属于API的项目(例如导入并在模块中使用的库模块)。

仅允许在模块级别使用通配符形式的导入(from module import *)。试图在类或函数定义中使用它将引发语法错误。

指定要导入的模块时,不必指定模块的绝对名称。当模块或包包含在另一个包中时,可以在同一个顶层包中进行相对导入,而不必提及包名称。通过在from之后的指定模块或包中使用前导点(leading dots ),可以指定向上遍历当前包层次结构的高度,而无需指定确切的名称。一个前导点表示被导入的模块所在的当前包。两个点表示上一个包级别。三点是上升两级,等等。

所以,如果你从一个pkg包的模块中执行“from . import mod”,将会导致导入“pkg.mod”。如果你在“pkg.subpkg1”中执行“from ..subpkg2 import mod ”将会导致导入“pkg.subpkg2.mod”。相对导入的规范包含在“Package Relative Imports ”部分。

importlib.import_module(),用于支持动态确定要加载的模块的应用程序。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alexabc3000

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值