模块

本节主要内容:
1. 模块
2. import
3. from xxx import xxx

一、模块

  ⾸先,我们先看⼀个老⽣常谈的问题. 什么是模块. 模块就是⼀个包含了python定义和声
明的⽂件, ⽂件名就是模块的名字加上.py后缀. 欢聚话说我们⽬前写的所有的py⽂件都可以
看成是⼀个模块但是我们import加载的模块⼀共分成四个通⽤类别:

  为什么要使⽤模块? 为了我们写的代码可以重⽤. 不⾄于把所有的代码都写在⼀个⽂件
内. 当项⽬规模比较⼩的时候. 完全可以使⽤⼀个py搞定整个项⽬的开发. 但是如果是⼀个⾮
常庞⼤的项⽬. 此时就必须要把相关的功能进⾏分离. ⽅便我们的⽇常维护. 以及新项⽬的开
发.

  如何使⽤模块? 我们已经⽤过很多模块了. 导入模块有两种⽅式
  1. import 模块
  2. from xxx import xxxx

二、import

  首先,我们先看import,在使用import的时候,我们先创建一个ManV.py(漫威)。在该文件中

创建一些人物和一些电影名字,代码如下:

hero1 = "钢铁侠"
hero2 = "小辣椒"

def fight_one():
    print("复仇者联盟1")
def fight_two():
    print("复仇者联盟2")
def fight_three():
    print("复仇者联盟3")

  接下来,斯坦李老爷子上场。

import ManV #第一种导入模块方式
from ManV import fight_one #第二种导入模块方式
fight_one()

# ManV.marry()
ManV.fight_two()
ManV.fight_three()

  此时我们在(StanLi.py)斯坦李模块中引入了ManV.py模块

  在Python中模块是不能够重复导入的。当重复导入模块时。系统会根据sys.modules来判断该模块

是否已经导入了。如果已经导入。则不会重复导入。

  导入模块的时候都做了些什么?首先。在导入模块的一瞬间。python解释器会先通过sys.modules

来判断该模块是否已经导入了该模块。如果是已经导入了则不在导入。如果该模块还未导入过,则系统

会做这三件事:

  1. 为导入的模块创⽴新的名称空间
  2. 在新创建的名称空间中运⾏该模块中的代码
  3. 创建模块的名字. 并使⽤该名称作为该模块在当前模块中引⽤的名字.

我们可以使用globals来查看模块的名称空间:

print(globals())

结果:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001AB9D6DC1D0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/python_workspace_s18/day25 模块和包/StanLi.py', '__cached__': None, 'ManV': <module 'ManV' from 'D:\python_workspace_s18\day25 模块和包\ManV.py'>, 'fight_one': <function fight_one at 0x000001AB9D7B4048>}

  注意。由于模块在导入的时候会创建其自己的命名空间。所以,我们在使用模块中的变量的时候一般是不会产生冲突的。

  注意,在模块中使用global。我们之前说global表示把全局的内容引入到局部。但是,这个全局指的是py文件。换句话,global指向的是模块内部,并不会改变外部模块的内容。

为什么会这样呢??
大家共享了同一个模块的名称空间

  如何解决呢??

  ⾸先. 我们不能去改python. 因为python的规则不是我们定的. 只能想办法不要改变主
⻆的名字. 但是.在Manv.py⾥我就有这样的需求. 那此时就出现了. 在Manv.py被执⾏的时候要执⾏
的代码. 在Manv.py被别⼈导入的时候我们不想执⾏这些代码. 此时, 我们就要利⽤⼀下__name__
这个内置变量了. 在Python中. 每个模块都有⾃⼰的__name__ 但是这个__name__的值是不

定的. 当我们把⼀个模块作为程序运⾏的入⼝时. 此时该模块的__name__是"__main__" , ⽽
如果我们把模块导入时. 此时模块内部的__name__就是该模块⾃⾝的名字

在Manv.py里

print(__name__)
# 此时如果运⾏该⽂件. 则__name__是__main__

在StanLi.py里
import Manv
#此时打印的结果是"Manv"

  我们可以利用这个特性来控制模块内哪些代码是在被加载的时候就运行的。哪些是在模块被别人导入的时候就要执行的。也可以屏蔽掉一些不希望别人导入就运行的代码。尤其是测试代码。

hero1 = "钢铁侠"
hero2 = "小辣椒"

def fight_one():
    print("复仇者联盟1")
def fight_two():
    print("复仇者联盟2")
def fight_three():
    print("复仇者联盟3")

def marry():
    print(f"{hero1}和{hero2}过上了幸福的生活")

def gai(name):
    global hero1
    hero1 = name

if __name__ == '__main__':
    fight_one()
    fight_two()
    fight_three()
    gai("123")
    marry()

  

  我们还可以对 导入的模块进行重新命名:

#在StanLi.py中
import ManV as mv
mv.fight_one()
mv.fight_two()
mv.fight_three()

结果:

复仇者联盟1
复仇者联盟2
复仇者联盟3

  一次可以引入多个模块

import time, random, json,ManV

  但是没有几个人会这样写,因为会被人给打死!!

  正确的导入模块的顺寻:

  1. 所有的模块导入都要写在最上⾯. 这是最基本的
  2. 先引入内置模块
  3. 再引入扩展模块
  4. 最后引入你⾃⼰定义的模块

三、from xxx import xxx

  在使⽤from的时候, python也会给我们的模块创建名称空间. 这⼀点和import是⼀样
的. 但是from xxx import xxx的时候. 我们是把这个空间中的⼀些变量引入过来了. 说⽩了. 就
是部分导入. 当⼀个模块中的内容过多的时候. 我们可以选择性的导入要使⽤的内容.

from ManV import fight_one
fight_one()

  此时是可以正常运行的。但是我们省略了之前的模块。直接函数()就可以执行了,并且from语句也支持一行语句导入多个内容。

from ManV import fight_one,fight_two,fight_three
fight_one()
fight_two()
fight_three()

这样虽然可以但是不推荐,不清晰

  同样支持 as

from ManV import fight_one as fight1
fight1()
# fight_one() #报错

  最后看一下from的坑。当我们从一个模块中引入一个变量的时候。如果当前文件中出现了重名的

变量时,会覆盖掉模块引入的那个变量。

from ManV import hero1
hero1 = "托尼斯塔克"
print(hero1)

  所以不要重名。切记,不要重名!!!不仅仅时变量名不要重复。我们自己创建的py文件的名字不要和系统内置的模块重名!!否则,引入的模块都是python内置的模块!!切记!切记!

原文地址:https://www.cnblogs.com/guchenxu/p/10197230.html