0086-【Python系统】-python的导入语法1

导入:

Python能对模块module和包package进行导入。
当你在一个模块中写的代码需要使用到其他模块或者包的代码要怎么办?导入它!

Python模块

实际上就是一个文件,它的文件格式为.py

一个Python包

就是一个文件夹folder,里面含有模块文件(在Python 2中,这个文件夹要有一个__init__.py文件)

工作原理

但是这个导入到底是如何工作的呢?假如你导入了一个模块,代码如下:
import abc

1. sys.modules

Python首先要做的就是在sys.modules中查找这个abc名称。它是先前曾被导入过的所有模块的缓存。简单来说,就是之前被导入过的模块,都被暂时保存在里面。

2. 内置的模块

如果在这个缓存中找不到这个名称,Python接下来会去内置的模块 built-in modules中查找。这些内置模块是Python预装的,可以在Python标准库中查看详情。

3. sys.path

假如还是没能在内置模块中找到它,Python将会去sys.path 定义的文件夹列表中搜索。通常来说,这个列表会包括当前目录,并且会先在里面搜索。

当Python找到了模块,它会将这个模块绑定到局部作用域。这就表示当前这个 abc 已经被定义了并且在被当前文件使用而不会抛NameError的异常。

如果这个模块名没有被找到,有就会抛出ModuleNotFoundError这个异常。你可以在Python的官方文档找到更多内容。

语法

现在你已经了解导入的工作原理了,让我们来看一下它的语法吧。你可以导入包和模块。(要注意一下,导入一个包的时候,实际上就是导入包里面的__init__.py作为模块)你也可以从一个包或者模块中导入指定的对象。

一般有两种导入的方法。当你使用第一个,你可以直接导入该资源,如下:
1)abc可以是一个包或者模块
import abc

2)当你使用第二种语法,你从其他包或者模块中导入资源。看下面这个例子:
from abc import xyz

xyz可以是一个模块、子包subpackage、对象object,例如类class或者函数function。

你也可以选择重命名导入的资源,如下:
import abc as other_name

这会在脚本中重命名这个已经导入的模块abc为other_name。现在必须使用other_name进行引用,不然就不被识别。

规范

PEP8 是Python的官方编码规范,里面有几个点也是适用于导入规范,以下是总结:

  1. 导入应该总是写在最前面,但需尾随任何模块单行注释和文档注释。

  2. 导入应该根据导入的内容进行分类,一般有三种:

  • 导入标准库(Python的内置模块)
  • 导入相关的第三方包(不属于当前应用的第三方包)
  • 导入本地应用的模块(属于当前应用的模块)
  1. 每一组的导入都应该用空白行分隔

请看下面这个例子:

"""展示一个标准的导入规范

注意,导入语句应该位于文档注释之后

"""

# 导入标准库
import datetime
import os

# 导入第三方库
from flask import Flask
from flask_restful import Api
from flask_sqlalchemy import SQLAlchemy

# 导入本地模块
from local_module import local_class
from local_package import local_function

以上的导入语句被分成了三个部分,通过空白行分隔。并在每一个部分中,是根据字母排序的。

绝对导入

绝对导入通过使用被导入资源在项目根目录的完整路径进行导入。

语法与实例
假如你有以下目录结构:

└── project
   ├── package1
   │   ├── module1.py
   │   └── module2.py
   └── package2
       ├── __init__.py
       ├── module3.py
       ├── module4.py
       └── subpackage1
           └── module5.py

这里有个目录project,它包含了两个子目录:package1和package2。其中package1有两个文件:module1.py和module2.py

package2目录有三个文件:两个模块, module3.py和module4.py,也有一个初始化文件 init.py。并且也包括一个目录,subpackage,它包含一个文件,module5.py

我们假设以下内容:

  1. package1/module2.py有一个函数,叫function1

  2. package2/__init.py有一个类,叫class1

  3. package2/subpackage1/module5.py有一个函数,叫function2

以下是绝对导入的例子:

from package1 import module1
from package1.module2 import function1
from package2 import class1
from package2.subpackage1.module5 import function2

要注意你必须在顶级包目录top-level package下提供每个包或者文件具体的路径。某种程度上和其文件路径相似,但是我们会使用点dot(.),而不用斜线slash(/)。

优缺点

应该优先考虑使用绝对路径,因为其更简单明了。使用它后,仅通过导入语句,就知道资源是从哪里导入的。而且,即使当前位置的导入语句改变了,绝对导入还是会保持有效。并且事实上,PEP8 推荐使用绝对导入。

当然,有时候绝对路径会变得冗长,取决于目录结构的复杂程度。想象一下以下这个语句:

from package1.subpackage2.subpackage3.subpackage4.module5 import function6

相对导入在这种情况下是一个绝佳的选择!


相对导入

相对导入指定了被导入资源是相对于当前的位置 - 也就是,这个位置就是导入语句所在的地方。有两种类型的相对导入:隐式和显式。隐式相对导入已经在Python3中被弃用了,所以这里我就不多讲了。

语法和实例
语法和实例

相对导入的语法取决于当前的位置和被导入模块、包以及对象的位置。以下是一些例子:

from .some_module import some_class
from ..some_package import some_function
from . import some_class

你能看到至少有一个点在每一个导入语句的前面。相对导入利用点符号来指定位置。

单个点表示模块或者包的引用是在同一个位置的同一个目录下。两个点表示它是在当前位置的父目录中 - 意思是指上一级目录。三个点表示它位于祖父母目录中,以此类推。如果你使用类Unix系统的话,一定有熟悉的感觉!

假设你有和之前一样的目录结构:

└── project
   ├── package1
   │   ├── module1.py
   │   └── module2.py
   └── package2
       ├── __init__.py
       ├── module3.py
       ├── module4.py
       └── subpackage1
           └── module5.py

这里有个目录project,它包含了两个子目录:package1和package2。其中package1有两个文件:module1.py和module2.py

package2目录有三个文件:两个模块, module3.py和module4.py,也有一个初始化文件 init.py。并且也包括一个目录,subpackage,它包含一个文件,module5.py

重温以下内容:

  1. package1/module2.py有一个函数,叫function1

  2. package2/__init.py有一个类,叫class1

  3. package2/subpackage1/module5.py有一个函数,叫function2

你可以通过以下方法在package1/module1.py文件中导入导入function1:

# package1/module1.py

from .module2 import function1

你在这里只需要使用一个点,因为module2.py和当前的模块module1.py是在同一个路径下面。

你也可以在package2/module3.py中导入class1和function2通过以下方法:

# package2/module3.py

from . import class1
from .subpackage1.module5 import function2

在第一个导入语句中,单个点代表你从当前包中导入class1。要谨记,导入一个包实际上是导入包里的__init__.py文件作为模块。

第二个导入语句中,你再次使用了单个点,这是因为subpackage1和当前模块module3.py是在同一个目录中。

优缺点

相对导入最明显的优点就是非常简洁。取决于当前的位置,它可以将之前那可笑的冗长语句缩减到以下:

from ..subpackage4.module5 import function6

不幸的是,相对导入可能会引起混乱,特别是一些目录结构可能会改变的共享项目。且相对导入不像绝对导入那样可读,不能轻易的从导入语句中查看资源被导入的位置。

结论

要记住,一般情况下,你应该选择使用绝对导入而不使用相对导入,除非路径非常的复杂,不然会使导入语句冗长。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值