Fork me on GitHub

day 15

1. 模块的四种形式

如果把 python 比作手机,pip就是手机的应用商店,模块就是 手机里的 App 。

在Python中,总共有以下四种形式的模块:

  1. 内置模块:python解释器内自带的模块(手机的系统 App )
  2. 自定义模块:使用python编写的xxx.py文件
  3. 第三方模块:需要使用pip安装的模块(应用商店下载的 App )
  4. 包:把一系列模块组织到一起的文件夹(注:文件夹下有一个\_\_init\_\_.py文件,该文件夹称之为包)

2. 导入模块的两种方式

2.1 import 模块名

import time # 导入 time 模块
time.sleep(1) # 延时 1s

import 模块名首次导入过程中发生的三件事:

  1. 开辟内存空间,内存空间命名为time
  2. time.py中的所有代码读入名称空间,然后运行
  3. 通过time.方法名使用time模块中的方法

2.2 from 模块名 import 具体的功能

from time import sleep
sleep(1)

from 模块名 import 具体的功能首次导入过程中发生的三件事:

  1. 开辟内存空间,内存空间命名为time
  2. time.py中的所有代码读入名称空间,然后运行
  3. 在当前执行文件中拿到一个sleep()模块名

2.3 两种方法的比较

  • 相同点:
    1. 两者都会执行模块对应的文件,两者都会产生模块的名称空间
    2. 两者调用功能时,需要跑到定义时寻找作用域关系,与调用位置无关
  • 不同点:
    1. 使用导入模块的方法时,import需要加前缀;from...import...不需要加前缀
    2. 使用 from...import...容易与当前执行文件中名称空间中的名字冲突

3. 循环导入问题

理解核心:

导入文件时发生的三件事:

  1. 以模块为准创造一个模块的名称空间(导入模块,只会开辟一次内存空间)
  2. 执行模块对应的文件,将执行过程中产生的名字都丢到模块的名称空间
  3. 在当前执行文件中拿到一个模块名

3.1 现象

假设有两个文件 file1.py 和 file2.py :

# file1.py
from file2 import y

x = 'from file2'

print(y)
# file2.py
from file1 import x

y = 'from file2'

print(x)

对于以上两个文件:

如果运行 file1,运行结果:

ImportError: cannot import name 'y' from 'file2' 

如果运行 file2,运行结果:

ImportError: cannot import name 'x' from 'file1' 

这种问题就是由于循环导入引起的。

3.2 解决方案 1

# file1.py
x = 'from file2'

from file2 import y

print(y)
# file2.py
y = 'from file2'

from file1 import x

print(x)

对于以上两个文件:

如果运行 file1,运行结果:

from file2
from file1
from file2

如果运行 file2,运行结果:

from file1
from file2
from file1

虽然解决了错误,但是得到了三个结果,显然不是我们想要的内容。

3.3 解决方案2

利用函数定义阶段只识别语法,不执行代码的特性,将代码写进函数里面

def file1():
    from file2 import y

    print(y)


x = 'from file1'

# file1()
def file2():
    from file1 import x

    print(x)


y = 'from file2'

# file2()

对于以上两个文件:

如果运行 file1(需要调用f1)运行结果:

from file2

如果运行 file2(需要调用f2)运行结果:

from file1

这种方法可以解决循环导入的问题,且达到了预期的输出。

最好的解决方法是不要出现循环导入。

4. 模块的搜索路径

4.1 模块的搜索顺序

导入模块时查找模块的顺序是:

  1. 先从内存中已经导入的模块中寻找
  2. 内置的模块
  3. 自定义模块
  4. 环境变量sys.path中找

4.2 环境变量

print(sys.path)

打印结果:

# # 导入模块的时候,解释器会按照列表的顺序搜索,直到找到第一个模块
['(当前执行文件自己保存的位置)相对路径下的当前目录', '当前执行文件的根目录', 'D:\\Program Files\\JetBrains\\PyCharm 2019.2.2\\helpers\\pycharm_display', 'D:\\Program Files\\Python\\Python37\\python37.zip', 'D:\\Program Files\\Python\\Python37\\DLLs', 'D:\\Program Files\\Python\\Python37\\lib', 'D:\\Program Files\\Python\\Python37', 'D:\\Program Files\\Python\\Python37\\lib\\site-packages', 'D:\\Program Files\\JetBrains\\PyCharm 2019.2.2\\helpers\\pycharm_matplotlib_backend']

5. python文件的两种用途

5.1 执行文件

当前正在运行的文件

5.2 模块文件

当 file1 导入 file2 ,运行file1 时,file2 就是模块文件

当 file2 导入 file1 ,运行file2 时,file1 就是模块文件

5.3 __name__

__name__ 是每个文件独有的,当该文件作为执行文件运行时, __name__ 等于'main';当该文件作为模块文件导入时, __name__ 等于文件名。

posted @ 2019-09-26 17:07  Yugaliii  阅读(146)  评论(0编辑  收藏  举报