模块与包的使用

模块的基础

模块:一堆函数的集合体

自第一模块:如果你自己写一个py文件,在文件内写入一堆函数,则它被称为自定义模块,即使用python编写的.py文件

第三方模块:已被编译为共享库或DLL的C或C++扩展

内置模块:使用C编写并链接到python解释器的内置模块

包:把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)

import与from...import

import首次导入模块发生了3件事:

  1. 以模块为准创造一个模块的名称空间
  2. 执行模块对应的文件,将执行过程中产生的名字都丢到模块的名称空间
  3. 在当前执行文件中拿到一个模块名

模块的重复导入会直接饮用之前创造好的结果,不会重复执行模块的文件,即重复导入会发生:spam=spam=模块名称空间的内存地

import spam, time, os

# 推荐使用下述方式
import spam
import time
import os

from...import...首次导入模块发生了3件事:

  1. 以模块为准创造一个模块的名称空间
  2. 执行模块对应的文件,将执行过程中产生的名字都丢到模块的名称空间
  3. 在当前执行文件的名称空间中拿到一个名字,该名字直接指向模块中的某一个名字,意味着可以不用加任何前缀而直接使用
  • 优点:不用加前缀,代码更加精简
  • 缺点:容易与当前执行文件中名称空间中的名字冲突
# spam.py

__all__ = ['money', 'read1']  # 只允许导入'money'和'read1'
# run.py
from spam import *  # 导入spam.py内的所有功能,但会受限制于__all__

import和from...import...的异同

相同点:

  1. 两者都会执行模块对应的文件,两者都会产生模块的名称空间
  2. 两者调用功能时,需要跑到定义时寻找作用域关系,与调用位置无关

不同点

  1. import需要加前缀;from...import...不需要加前缀

循环导入问题

解决方案

我们可以使用函数定义阶段只识别语法的特性解决循环导入的问题,我们也可以从本质上解决循环导入的问题,但是最好的解决方法是不要出现循环导入。

# m1.py
print('from m1.py')


def func1():
    from m2 import x
    print(x)


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


y = 'm1'
from m2 import x

python文件的两种用途

python文件总共有两种用途,一种是执行文件;另一种是被当做模块导入。

编写好的一个python文件可以有两种用途:

  1. 脚本,一个文件就是整个程序,用来被执行
  2. 模块,文件中存放着一堆功能,用来被导入使用
# aaa.py

x = 1


def f1():
    print('from f1')


def f2():
    print('from f2')


f1()
f2()
# run.py

import aaa

如果直接运行run.py会直接运行aaa.py中的f1()f2(),但是如果我们在aaa.py中加上if __name__ == '__main__':这句话,则可以防止运行run.py时执行f1()f2()。因为当aaa.py被直接执行,即当做执行文件的时候__name__ == '__main__'; 在aaa.py被当做模块直接运行的时候__name__ == 'aaa'。由此可以让aaa.py在不同的场景下有着不同的用法。

# aaa.py

x = 1


def f1():
    print('from f1')


def f2():
    print('from f2')


if __name__ == '__main__':
    f1()
    f2()

包是模块的一种形式,包的本质就是一个含有__init__.py的文件夹。

模块与包

导入模块发生的三件事:

  1. 创建一个包的名称空间
  2. 执行py文件,将执行过程中产生的名字存放于名称空间中。
  3. 在当前执行文件中拿到一个名字aaa,aaa是指向包的名称空间的

导入包发生的三件事:

  1. 创建一个包的名称空间
  2. 由于包是一个文件夹,无法执行包,因此执行包下的__init__.py文件,将执行过程中产生的名字存放于包名称空间中(即包名称空间中存放的名字都是来自于__init__.py)
  3. 在当前执行文件中拿到一个名字aaa,aaa是指向包的名称空间的

导入包就是在导入包下的__init__.py,并且可以使用以下两种方式导入:

  1. import ...
  2. from ... import...

注意事项

包内所有的文件都是被导入使用的,而不是被直接运行的

包内部模块之间的导入可以使用绝对导入(以包的根目录为基准)与相对导入(以当前被导入的模块所在的目录为基准),推荐使用相对导入

当文件是执行文件时,无法在该文件内用相对导入的语法,只有在文件时被当作模块导入时,该文件内才能使用相对导入的语法

凡是在导入时带点的,点的左边都必须是一个包,import aaa.bbb.m3.f3错误

原文地址:https://www.cnblogs.com/1naonao/p/10994586.html