Python学习 Day 025 -模块相关

主要内容:

  • 1. 模块
  • 2. import
  • 3. from xxx import xxx

1.模块

   (1)模块的概述

   模块就是一个包含了python定义和声明的文件, 文件名就是模块的名字加上.py后缀,也就是说我们目前写的所有的py文件都可以看成是一个模块

   但是我们import加载的模块一共分成四个通用类别.

  •  使用pyhton编写的py文件
  •  已被变异为共享库或者DLL或C或者C++的扩展
  •  包好⼀组模块的包.
  •  使用c编写并连接到python解释器的内置模块

(2)模块的使用缘由

使用模块是为了我们写的代码可以重用,不至于把所有的代码都写在一个文件内,当项目规模比较小的时候. 完全可以使用一个py搞定整个项目的开发,但是如果是一个非常庞大的项目,此时就必须要把相关的功能进行分离,方便我们日常维护,以及新项目的开发.   

(3)模块的使用             

     导入模块有两种方式           

  • import 模块           
  • from xxx import xxxx

2. import

print("片头曲,倚天屠龙........")
main_person_man = "张无忌"
main_person_woman = "赵敏"

bad_person_one = "成昆"
bad_person_two = "周芷若"

def fight_on_light_top():
    print(main_person_man, "粉碎了",bad_person_one ,"的阴谋")

def fight_in_shaolin():
    print(main_person_man, "粉碎了", bad_person_two, "的阴谋")

打开另一个py文件

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

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

此时在这个py文件中引入了yitian模块

注: 在Python中模块是不能够重复导入的,当重复导入模块时,系统会根据sys.modules来判断该模块是否已经导入了,如果已经导入,则不会重复导

import sys
print(sys.modules.keys())   # 查看导⼊入的模块.
import yitian   # 导⼊入模块. 此时会默认执行该模块中的代码
import yitian   # 该模块已经导入过了. 不会重复执行代码
import yitian
import yitian 

导入模块(import之后)时候做了什么?

  • python解释器会先通过 sys.modules来判断该模块是否已经导入了该模块. 如果已经导入了则不再导入.
  • 为导入的模块创立新的名称空间           
  • 在新创建的名称空间中运行该模块中的代码           
  • 创建模块的名字,并使用该名称作为该模块在当前模块中引用的名字.

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

import yitian
print(globals())
#{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000018141DE4A90>,
#  '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/Python_workspace/day 025/金庸.py', '__cached__': None,
#  'yitian': <module 'yitian' from 'E:\\Python_workspace\\day 025\\yitian.py'>}

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

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指向的是模块内部. 并不会改变外部模块的内容 

print("片头曲,倚天屠龙........")
main_person_man = "张无忌"
main_person_woman = "赵敏"

bad_person_one = "成昆"
bad_person_two = "周芷若"

def fight_on_light_top():
    print(main_person_man+"粉碎了"+bad_person_one+"的阴谋")

def fight_in_shaolin():
    global bad_person_two
    bad_person_two = "战五渣"
    print(main_person_man+"粉碎了"+bad_person_two+"的阴谋")


# 调用方
import yitian
bad_person_two = "宋青书"
yitian.fight_in_shaolin()
print(yitian.bad_person_two)    # 战五渣
print(bad_person_two)   # 宋青书,并没有改变当前模块中的内容. 所以模块内部的 global只是用于模块内部

特别特别要注意:如果我们在不同的模块中引入了同一个模块. 并且在某一个模块中改变了被引入模块中的全局变量,则其他模块看到的值也跟着边,原因是python的模块只会引入一次,大家共享同一个名称空间

金庸: 
import yitian 
yitian.main_person_man = "灭绝师太" 


金庸二号:
import yitian   
import 金庸 
print(yitian.main_person_man) # 灭绝师太

 上述问题出现的原因:             

  • 大家共享同一个模块的名称空间          
  • 在金庸里改变了主角的名字         

可以利用一下__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()) 

{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x103209438>, 

'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__':

'/Users/sylar/PycharmProjects/oldboy/模块/模块/金庸.py', '__cached__': None, 'yt': <module 'yitian' from '/Users/sylar/PycharmProjects/oldboy/模块/模 块/yitian.py'>}

一次可以引入多个模块

import time, random, json, yitian

  正确的导入模块的顺序:           

  • 所有的模块导入都要写在最上面,这是最基本的           
  • 先引入内置模块           
  • 再引入扩展模块           
  • 最后引入你自己定义的模块

 

3. 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内置的模块. 切记, 切记. 

 

posted @ 2018-10-11 17:09  一路向北_听风  阅读(187)  评论(0编辑  收藏  举报