模块以及包

一:模块

【1】:

  (1)定义:模块是一系列功能的集合体

 

  (2)好处:

    (1)大量的代码分模块 组织结构更加清晰

    (2)不同的文件对应不同的功能 调用方便

    (3)模块拿来就可以使用 提升开发效率

 

【2】:

  (1)来源方式:

    (1)python自定义的模块

    (2)第三方模块

    (4)自己手工定义的

 

  (2)表现形式:

    (1)一个.py文件即为一个模块

    (2)被编译为共享库或DLL的C或者C++扩展

    (3)把一系列模块组织到一起的文件夹

    (4)使用C语言编写的内置模块

 

【3】

  (1)模块的调用方式

    import + 模块名

PS:在模块导入的注意事项

    (1)执行文件: import + 模块名

    (2)被导入模块:import 后面跟的模块名

例如:

  

# 执行文件
import spam
res = spam
print(res)  # <module 'spam' from 'D:\\Workstaion\\Practice Code\\spam.py'>


# 被导入模块
print('start from the spam.py')

money=1000

def read1():
    print('spam模块:',money)

def read2():
    print('spam模块')
    read1()

def change():
    global money
    money=0

print('end from the spam.py')
被导入模块

PS:其只会执行第一次导入的模块 不会执行第一次之后的模块

  

(2)模块导入流程图

  (1)首先会执行模块代码

  (2)将模块代码存放入模块开辟的名称空间中

  (3)执行文件本地名称空间存放指向模块的名字

如图所示:

 

 (3)被导入模块拥有自己独立名称空间

例如:

money = 100
print(spam.money)  # 1000 指名道姓就是读取spam这个模块里代码
本地money与模块money
import spam
money = 100
read1 = '本地文件代码'
print(spam.read1)    # <function read1 at 0x0000000002819A60> 通过内存地址取值
print(spam.read1())  # spam模块: 1000
本地read1与模块read1
import spam
money=1000
spam.change()       # 调用模块里函数
print(spam.money)   # 0 
模块修改全局

 

 (3)模块另起别名:

作用:当模块名称比较长的时候,可以通过另起别名方便调用

例如:

import spam as SR
print(SR.money)     # 1000

 

(4)一次性导入多个模块

例如:

import os ,sys,time  # PS:不推荐这样写

 

【4】

(1)模块导入方式二:

 定义方式:from...impo...

例如:

from spam import read1

 

(2)

from...import... 与 import 区别

  (1)在前者中以后调用的时候不需要再在加上模块名的前缀

 

(3)from...import ...优缺点

  优点:调用更加方便

  缺点:容易与本地存在的变量名产生冲突

例如:

from spam import read1
read1 = 'SR'
print(read1)  # SR

原因:

read1 = 'SR'
from spam import read1
print(read1)  # <function read1 at 0x00000000029E9A60>

PS:

(1)首先在执行文件内存空间中会包含一个read1的内存地址

(2)在调用模块里的read1 会将内存地址从原来指向SR改成指向模块里的代码

图解:

 

 (4)from...import... * 

作用:

(1)当模块中有太多名字需要被导入的时候可以一次性导入全部

(2)但是不推荐这样 虽然一次性有很多都需要导入 但是假如模块中很多名字还是不需要导入的 我们也将不需要导入的给导入了 浪费内存空间

例如:

from spam import *
print(money)        # 1000

print(read1)        # <function read1 at 0x00000000021E9A60>

print(read2)        # <function read2 at 0x00000000021E9AE8>

print(change)       # <function read2 at 0x00000000021E9AE8>
from...import...*

PS:只是内部实验效果 假如真实环境中 模块有2000个名称需要被导入 但是模块总共有2w如果用该方法就会平白多匹配1w8的名称

 

(5)__all__:

作用:将需要被导入模块的名字假如列表中 通过该方法调用列表 即调用需要的模块

例如:

from spam import *
print(money)        # 1000

print(read1)        # <function read1 at 0x00000000021E9A60>

print(read2)        # 报错 

print(change)       # 报错
__all__

 

 (6)模块循环导入问题:

  (1)程序设计不合理

  (2)程序设计阶段应该避免

例如:

#m1.py
print('正在导入m1')
from m2 import y

x='m1'

#m2.py
print('正在导入m2')
from m1 import x

y='m2'

#run.py
import m1

执行run.py会抛出异常
正在导入m1
正在导入m2
Traceback (most recent call last):
  File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/aa.py", line 1, in <module>
    import m1
  File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m1.py", line 2, in <module>
    from m2 import y
  File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m2.py", line 2, in <module>
    from m1 import x
ImportError: cannot import name 'x'
循环导入

 解释:

  (1)首先run在调用m1之前会开辟一个名称空间

 

  (2)执行m1的代码 首先打印正在导入m1 在调用m2开辟一个新的名称空间

 

  (3)调用m2打印正在导入m2  然后执行导入的代码 但是这时候想m1取值 而m1本身内部没有值 故报错

 

   (4)同理m1向m2中索值 但是m2中也不存在y 故报错

 

 解决办法:

  (1)将模块索取值放在导入模块之上

  (2)当名称空间内部先有值

例如:

print('正在导入m1')

x='m1'

from m2 import y


print('正在导入m2')


y='m2'

from m1 import x

import m1
循环导入解决办法一

 

 (7)py文件的区分:

  (1)不同的人对不同的py文件有不同的定义

  (2)当别人使用我们写的代码 但是自己本身代码在执行 对别人来说执行属于无用的

例如:

# 导入文件
def index():
    print('index')

def func():
    print('func')

index()
func()

# 执行文件
import md

import md

'''
index
func
PS:调用模块的执行结果 但是该结果对我无用

'''
文件区分

解决办法:__name__

  (1)当文件为执行文件的时候其打印结果为__main__

  (2)当文件被当做模块导入的时候其打印结果为模块名称

# 模块
def index():
    print('index')

def func():
    print('func')


if __name__ == "__main__":
    index()
    func()

 

(7)模块的查找顺序

  (1)内存

  (2)内置空间

  (3)sys.path:在该情况下,其将一堆文件组成一个列表 且第一个文件永远为执行文件当前文件夹

PS:如果想在sys.path添加文件路径可以通过append执行

 

(8)绝对导入相对导入  

   (1)绝对导入:

     (1)以执行文件所在文件文件夹路径为准

     (2)且无轮在执行文件还是导入文件都适用

  (2)相对导入:

    (1).代表当前所在路径

    (2)..代表上一级文件所在路径

    (3)相对导入不能再执行文件中使用

 

二:包

(1)什么是包

定义:包就是一系列模块的结合体

基本概念:其实就是含有__init__的文件夹 主要就是用文件夹将一些模块打包组织一起

PS:

(1)在pyhton3中如果文件夹不含有__init__在调用的时候不会报错 而在python2中如果如果文件夹不含有__init__会报错

(2)包的目的不是为了执行 而是为了被使用

 

(2)使用包的好处

(1)随着功能越写越多代码组织结构不清晰 需要用多个文件夹存储不同的功能块

(2)用包将各个功能组织连接一起 提高代码的结构性 扩展性

 

(3)首次导入包过程

  (1)首先执行文件产生一个名称空间

  (2)包内部创建一个__init__的名称空间 然后执行包内部代码 将内部代码名称存入__init__的名称空间中

  (3)执行文件获取到一个指向__init__名称空间的名字

 

(4)包的导入方式

  方式一:import + 包名称

  方式二:from...import...

 

(5)绝对导入 相对导入

绝对导入与相对导入

# 绝对导入: 以执行文件的sys.path为起始点开始导入,称之为绝对导入
#        优点: 执行文件与被导入的模块中都可以使用
#        缺点: 所有导入都是以sys.path为起始点,导入麻烦

# 相对导入: 参照当前所在文件的文件夹为起始开始查找,称之为相对导入
#        符号: .代表当前所在文件的文件加,..代表上一级文件夹,...代表上一级的上一级文件夹
#        优点: 导入更加简单
#        缺点: 只能在导入包中的模块时才能使用
      #注意:
        1. 相对导入只能用于包内部模块之间的相互导入,导入者与被导入者都必须存在于一个包内
        2. attempted relative import beyond top-level package # 试图在顶级包之外使用相对导入是错误的,言外之意,必须在顶级包内使用相对导入,每增加一个.代表跳到上一级文件夹,而上一级不应该超出顶级包

 

 

  

 

posted @ 2019-07-16 16:39  SR丶  阅读(233)  评论(0编辑  收藏  举报