一、模块

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

1. 使⽤pyhton编写的py⽂件

2. 已被变异为共享库或者DLL或C或者C++的扩展

3. 包好⼀组模块的包.

4. 使⽤c编写并连接到python解释器的内置模块

 

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

 如何使⽤模块? 我们已经⽤过很多模块了导入模块有两种⽅式:

 1. import 模块

 2. from xxx import xxxx

 

. import

 ⾸先我们先看import, 在使⽤import的时候, 我们先创建⼀个yitian.py,在该⽂件中创建⼀些武林前辈和⼀些打⽃场景代码如下

print("⽚头曲: music起~~~~~~~")

main_person_man = "张⽆忌"

main_person_woman = "赵敏"

low_person_man_one = "成昆"

low_person_man_two = "周芷若"

def fight_on_light_top():

   print("光明顶⼤战", main_person_man, "破坏了", low_person_man_one, "的⼤阴谋")

def fight_in_shaolin():

   print("少林寺⼤战", main_person_man, "破坏了", low_person_man_two, "的⼤阴谋")

  

接下来⾦庸上场

import yitian

print(yitian.main_person_man) # 使⽤模块中定义好的名字

print(yitian.low_person_man_one)

yitian.fight_in_shaolin() # 调⽤模块中的函数

yitian.fight_on_light_top()

 

  

  此时我们在⾦庸模块中引入了yitian模块Python中模块是不能够重复导入的当重复导入模块时系统会根据sys.modules来判断该模块是否已经导入了如果已经导入则不会重复导入。

import sys

print(sys.modules.keys()) # 查看导⼊的模块.

import yitian # 导⼊模块. 此时会默认执⾏该模块中的代码

import yitian # 该模块已经导⼊过了. 不会重复执⾏代码

import yitian

import yitian

import yitian

import yitian

 

导入模块的时候都做了些什么? ⾸先在导入模块的⼀瞬间,python解释器会先通过sys.modules来判断该模块是否已经导入了该模块如果已经导入了则不再导入如果该模块

还未导入过则系统会做三件事

 

1. 为导入的模块创⽴新的名称空间

2. 在新创建的名称空间中运⾏该模块中的代码

3. 创建模块的名字. 并使⽤该名称作为该模块在当前模块中引⽤的名字.

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

 

print(globals())

 

注意由于模块在导入的时候会创建其⾃⼰的名称空间所以我们在使⽤模块中的变量的时候⼀般是不会产⽣冲突的

import yitian

main_person_man = "胡⼀菲"

def fight_in_shaolin():

 print(main_person_man, "⼤战曾⼩贤")

print(yitian.main_person_man) # 张⽆忌

print(main_person_man) # 胡⼀菲

yitian.fight_in_shaolin() # 倚天屠⻰记中的

fight_in_shaolin() # ⾃⼰的

  

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

 

模块 yitian 中:

print("⽚头曲. 啊! 啊~ 啊! 啊. 啊啊啊啊啊啊啊...")

main_person_man = "张⽆忌"

main_person_woman = "赵敏"

low_person_man_one = "成昆"

low_person_man_two = "周芷若"

def fight_on_light_top():

     print("光明顶⼤战", main_person_man, "破坏了", low_person_man_one, "的⼤阴

谋")

def fight_in_shaolin():

     global low_person_man_two # 注意看, 此时的global是当前模块. 并不会影响其他模块
     low_person_man_two = "战五渣"

     print("少林寺⼤战", main_person_man, "破坏了", low_person_man_two, "的⼤阴谋")

  

调⽤⽅:

import yitian

low_person_man_two = "刘海柱"

yitian.fight_in_shaolin()

print(yitian.low_person_man_two) # 战五渣

print(low_person_man_two) # 刘海柱. 并没有改变当前模块中的内容. 所以模块内部的global只是⽤于模块内部

 

特别要注意如果我们在不同的模块中引入了同⼀个模块并且在某⼀个模块中改变了被引入模块中的全局变量则其他模块看到的值也跟着变。 原因是python的模块只会引入

⼀次⼤家共享同⼀个名称空间。

⾦庸:

import yitian

yitian.main_person_man = "灭绝师太"

⾦庸⼆号:

import yitian

import ⾦庸

print(yitian.main_person_man) # 灭绝师太.

  

上述问题出现的原因:

 

1. ⼤家共享同⼀个模块的名称空间.

2. 在⾦庸⾥改变了主⻆的名字

  

如何解决呢?

   ⾸先我们不能去改python。因为python的规则不是我们定的只能想办法不要改变主⻆的名字但是在⾦庸⾥我就有这样的需求那此时就出现了在⾦庸被执⾏的时候要执⾏的代码在⾦庸被别⼈导入的时候我们不想执⾏这些代码此时, 我们就要利⽤⼀下__name__这个内置变量了Python每个模块都有⾃⼰的__name__ ,但是这个__name__的值是不定的当我们把⼀个模块作为程序运⾏的入⼝时此时该模块的__name__"__main__" , ⽽如果我们把模块导入时此时模块内部的__name__就是该模块⾃⾝的名字。

⾦庸:

print(__name__)

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

⾦庸⼆号:

import ⾦庸

#此时打印的结果是"⾦庸"

#我们可以利⽤这个特性来控制模块内哪些代码是在被加载的时候就运⾏的,哪些是在模块被别⼈导入的时候就要执⾏的,也可以屏蔽掉⼀些不希望别⼈导入就运⾏的代码,尤其是测试代码.

if __name__ == '__main__':

   yitian.main_person_man = "灭绝师太" # 此时, 只有从该模块作为⼊⼝运⾏的时候才会把main_person_man设置成灭绝师太

   print("哇哈哈哈哈哈") # 只有运⾏该模块才会打印. import的时候是不会执⾏这⾥的代码的

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

import yitian as yt # 导⼊yitian. 但是名字被重新命名成了yt,就好⽐变量赋值⼀样。

a = 1 
b = a yt.fight_in_shaolin() # 此时可以正常运⾏ # yitian.fight_in_shaolin() # 此时程序报错,因为引⼊的yitian被重命名成了yt print(globals())#打印出来看一下是不是被修改了。

 

⼀次可以引入多个模块

import time, random, json, yitian

 

 正确的导入模块的顺序:

 1. 所有的模块导入都要写在最上⾯. 这是最基本的

 2. 先引入内置模块

 3. 再引入扩展模块

 4. 最后引入你⾃⼰定义的模块

 

. from xxx import xxx

   第⼀⼤块关于import就说这么多接下来. 我们来看from xxx import xxx这种导入模块的效果在使⽤from的时候, python也会给我们的模块创建名称空间这⼀点和import是⼀样

但是from xxx import xxx的时候我们是把这个空间中的⼀些变量引入过来了说⽩了就是部分导入当⼀个模块中的内容过多的时候我们可以选择性的导入要使⽤的内容

from yitian import fight_in_shaolin

fight_in_shaolin()

  

   此时是可以正常运⾏的但是我们省略了之前的模块.函数(), 直接函数()就可以执⾏了, from语句也⽀持⼀⾏语句导入多个内容

from yitian import fight_in_shaolin, fight_on_light_top, main_person_man

fight_in_shaolin()

fight_on_light_top()

print(main_person_man)

#同样⽀持as

from yitian import fight_in_shaolin, fight_on_light_top, main_person_man as

big_lao

fight_in_shaolin()

fight_on_light_top()

print(big_lao)

   

  最后看⼀下from的坑当我们从⼀个模块中引入⼀个变量的时候如果当前⽂件中出现了重名的变量时会覆盖掉模块引入的那个变量

from yitian import main_person_man

main_person_man = "超级⼤灭绝"

print(main_person_man)

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

  我们现在知道可以使⽤importfrom xxx import xxx来导入⼀个模块中的内容那有⼀种特殊的写法: from xxx import * 。我们说此时是把模块中的所有内容都导入注意, 如果模块中没有写出__all__ 则默认所有内容都导入如果写了__all__ ,此时导入的内容就是在__all__列表中列出来的所有名字

# haha.py

__all__ = ["money", "chi"]

money = 100

def chi():

   print("我是吃")

def he():

   print("我是呵呵")

# test.py

from haha import *

chi()

print(money)

# he() # 报错