python基础:模块简介、模块的语句、绝对导入和相对导入

python基础:模块简介、模块的语句、绝对导入和相对导入

一、索引取值与迭代取值的差异

l1 =[11,22,33,44,55]
1.索引取值
   优点:可以任意位置,任意次数取值
   缺点:不支持无序类型的数据取值
2.迭代取值
   优点:支持所有类型的数据取值(无序有序都可以迭代取值)
   缺点:只能从前往后依次取值,无法后退

# 两者的使用需要结合实际应用场景  

二、模块简介

1.模块的本质
    内部具有一定功能(代码)的py文件、文件夹
  # 模块是最高级别的程序组织单元
  # 模块的作用: 1 将出现代码和数据封装起来以便再利用 2 同时提哦那个自包含的命名空间避免程序出现变量名冲突(模块的全局作用域变成了模块对象的属性命名空间)
  一个模块文件顶层定义的所有变量都变成了被导入的模块对象的属性,通过导入模块获得这个模块定义的工具的访问权,获得它的属性从而使用其中的工具。

  
2.python模块的历史
    python中的模块是让python的功能越来越强大的支撑
  
    python刚开始的时候所有搞其他编程语言的程序员都看不起 甚至给python起了个外号>>>:调包侠(贬义词)
 	  随着时间的发展项目的复杂度越来越高 上面那帮人也不得不用一下python 然后发现真香定律>>>:调包侠(褒义词)
      
3.python模块的表现形式
    1)py文件(py文件也可以称之为模块文件)
    2)含有多个py文件的文件夹(按照模块功能的不同划分不同的文件夹存储)
    3)已被编译为共享库或DLL的c或者C++扩展 # 了解
    4)使用C编写并链接到python解释器的内置模块 # 了解   
image-20221018164541572 image-20221018164821640

三、模块的分类

1.自定义模块
     程序员自己写的模块文件
  
2.内置模块
     python解释器提供的模块  #如 time模块
  
3.第三方模块
     别人写的模块文件(大佬写的模块)

四、导入模块的两种句式

1.import句式

'''强调:
  1. 一定要搞清楚谁是执行文件,谁是被导入文件
  2. 以后开发项目的时候py文件名称一般是纯英文
        不会有中文甚至空格
  3.导入模块文件不需要填写后缀名    
'''
1.import句式
  # 使导入者以一个整体获取一个模块,我们获取模块中的名称时,必须通过模块名点号来获取该模块的属性(点号运算语法 可以访问任何拥有属性的对象的属性)
  载入文件 a.py 并且能通过变量名a获取它所有的属性的权限,实际上import语句中模块名起到了两个作用: 1 识别加载的外部文件 2 同时 import也会变成赋值了被载入模块的变量
  
  1) import 句式底层原理 ,如图1  
      1 先产生执行文件的名称空间
      2 执行被导入文件的代码将产生的名字放入被导入文件的名称空间中
      3 在执行文件的名称空间中产生一个模块的名字
      4 在执行文件中使用该模块名 点(dot nonation)的方式使用模块名称空间中所有的名字 
      
  2) import句式中名称空间中名字的问题,如图
  
#举例
import a 
print(a.name)
a.func1()

​ 图1:import 句式底层原理

image-20221018152837593

​ 图2:import句式中名称空间中名字的问题

image-20221018153738134

2.from... import 句式

2.from... import 句式  # 直接点明要导入的模块中的变量名
# 允许导入者从一个模块文件中获取(复制)特定的名称,from语句可以让我们直接在脚本中使用复制后的名称,不需要通过模块

  from... import 句式底层原理 ,如图    
      1 先产生执行文件的名称空间
      2 执行被导入文件的代码将产生的名字放入被导入文件的名称空间中
      3 在执行文件的名称空间中产生对应的名字绑定模块名称空间中对应的名字
      4 在执行文件中直接使用名字就可以访问名称空间中对应的名字
   

# 举例
from a import name, func1

print(name)
func1
image-20221018100913232

1)Import 和 from是赋值语句

import将整个模块对象赋值给一个单独的名称
from将一个或者多个名称赋值给另一个模块中的同名对象

2) Import 和 from可以嵌套在if测试中,在函数def之中,在try语句中,但是只有它们所对应的Import 和 from语句被执行后,才可以使用

3.导入模块补充说明

1. import与 from... import 句式 两者的优缺点
   
   1) import句式:
    优点:不会发生名字冲突
    由于使用模块名称空间中的名字都需要模块名点的方式才可以用,所以不会轻易的被执行文件中的名字替换掉
    劣势:繁琐一点
     每次使用模块名称空间的名字都必须使用模块名点才可以
  
   2) from... import
    优点:简便
     指名道姓的导入模块名称空间中需要使用的名字,不需要模块名点
    劣势:会发生名字冲突  
     但是容易跟执行文件中名字冲突
  
2.重复导入模块
     解释器只会导入一次,后续重复导入语句并不会执行

3.起别名
     模块名很长可以用 as语句来起别名,为变量名较长的变量提供简短的别名,同时避免import语句覆盖脚本中已有的名称而引发的命名冲突
     
# 举例
import lizhierciyuan as lz  # 下面可以用lz点的方式使用lz的功能
from jigeerciyuan import jige as j
from a import name as n,func1 as f1 
  
4.涉及到多个模块导入的语句
  1)分开用import语句
import a
import jigeerciyuan

  2)用逗号隔开
import a, jigeerciyuan

# 用逗号隔开的方式,一般用于模块的功能相似,如果相似度不高可以使用第一种多个import来导入不同的模块
  

4.循环导入问题

1.循环导入
    两个文件之间彼此导入彼此,相互使用各自名称空间中的名字,极其容易报错
    
2.如何解决循环导入问题

    1 确保名字在使用之前就已经准备完毕了
    2 编写代码的过程中,应该尽可能避免出现循环导入(会浪费资源)
image-20221018105418616

五、判断文件类型

# 模块即可以当作模块文件导入,也可以当作独立的程序运行,而每个模块都有一个名为__name__的内置属性


1.__name__的使用:判断文件是否是执行文件
所有的py文件都可以直接打印__name__对应的值
  
  1)当py文件是执行文件(顶层文件)的时候,
  启动__name__就会被设置为字符串"__main__"
  2)当py文件是被导入文件的时候,启动__name__对应的就是模块名


# 举例
if __name__ == '__main__':  
    print('我是执行文件,我可以运行这里的子代码')
  
上述脚本可以用来区分所在py文件内python代码的执行,__name__变量充当了一饿使用模式标准符
# 常常用在  1 项目的启动文件中  2 模块开发阶段调用代码

2. from 模块 import*   语句
  1) 功能:from a import *  *默认是将模块名称空间中所有的名字导入(或取得模块顶层被复制的所有名称的副本)

  2)__all__ 和 from a import * 搭配使用

   __all__ =  ['名字1', '名字2'] 针对*限定导入的名字
  
image-20221018111026376

六、模块的查找顺序

1.内存
     使用了关键字 import或者 from 导入的时候内存可以临时储存,这时候删掉不会报错,运行之后内存释放再运行则找不到要导入的模块报错

2.内置
    1)当自定义模块和内置模块冲突,内置模块优先级更高
    2)命名模块名时,不要和内置模块冲突

# 举例
import time  # 有一个模块名称为 time (name = 'duo')

print(time)  #  <module 'time' (built-in)>   
# time是内置模块,所以打印模块显示time是内置模块

print(time.name)  # 报错 AttributeError: module 'time' has no attribute 'name'
       
3.执行文件所在的环境变量 sys.path(系统环境变量)
    一定要以执行文件为准
    我们可以将模块所在的路径也添加到执行文件的sys.path中
    
    
import sys
print(sys.path)  # 列表
sys.path.append(r'D:\pythonProject03\day17\mymd')
import ccc
print(ccc.name)   

# 往列表汇中添加数据值 insert append extend

七、绝对导入与相对导入

# 再次强调:弄清楚谁是执行文件,单次执行的时候模块的导入都以执行文件为准

1.绝对导入  # from句式
   站在执行文件的角度导入,按照项目的根目录为准导入

# 举例 按照项目根目录一层层往下查找  
from mymd import ccc  # 可以精确掉变量名 
from mymd.aaa.bbb.ccc import ddd  # 也可以精确到模块名
print(ccc.name)

2.相对导入  # 只能用在模块文件中,不能用在执行文件中使用
   不在依据执行文件所在的sys.path 而是以模块自身路径为准
# 不需要考虑执行文件路径,只要知道当前模块路径,就可以使用相对导入
# 相对导入使用频率低,一般用绝对导入即可,结构更加清晰

   .在路径中表示当前目录
   ..在路径中表示上一层目录
   ..\..在路径中表示上上一层目录 

八、包

多个py文件的的集合>>>:文件夹
  
专业:内部含有__init__.py的文件夹(python 2 必须要求,python 3不在乎)

九、包的具体使用

为了兼容性考虑,包中最好还是有__init__.py文件
一个包中的模块,在功能上是相似的,所以才能放在一个包中

1.如果只想用包中的某几个模块,那么还是按照之前的导入方式即可
from aaa import md1, md2
2.如果直接导入包名
  1)执行包下面的__init__.py文件
  2)产生一个新的名称空间用于存放__init__.py执行过程中产生的名字
  3)在当前执行文件所在的名称空间中得到一个名字 aaaaa,该名字指向__init__.py的名称空间
  # 导入包时并不会导入包下所有的子模块与子包

# 包中的__init__.py文件,可以看作包中其他py文件和 执行文件的桥梁,将包中的其他py文件导入__init__.py文件,在执行文件中就可以使用其他文件的属性

1.包的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。

​ 可以带有一连串的点,如import 顶级包.子包.子模块,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。

2、包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间

3、import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的 __ init __.py,导入包本质就是在导入该文件

image-20221019151432585
posted @ 2022-10-18 17:20  Duosg  阅读(234)  评论(0编辑  收藏  举报