python基础九(模块和包)

Posted coderxueshan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python基础九(模块和包)相关的知识,希望对你有一定的参考价值。

一 模块介绍

1、什么是模块?
模块就是一系列功能的集合体,分为三大类
I:内置的模块(python解释器内置)
II:第三方的模块
III:自定义的模块
一个python文件本身就是一个模块,文件名m.py,模块名叫m
ps:模块有四种形式
1)、使用python编写的.py
2)、已被编译为共享库或DLL的C或C++扩展
3)、把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包
4)、使用C编写并链接到python解释器的内置模块

2、为何要用模块
I:内置与第三方的模块拿来就用,无需定义,这种拿来主义,可以极大地提升自己的开发效率
II:自定义的模块
可以将程序的各部分功能提取出来放到一个模块中为大家共享使用
好处是减少了代码冗余,程序组织结构更加清晰
首次导入模块会发生3事?
1)、执行foo.py
2)、产生foo.py的名称空间,将foo.py运行过程中产生的名字都丢到foo的名称空间中
3)、在当前文件中产生的有一个名字foo,该名字指向2中产生的名称空间

之后的导入,都是直接引用首次导入产生的foo.py名称空间,不会重复执行代码
import foo
import foo
import foo
3、引用:
import foo
x = 222
print(foo.x)
print(x)
print(foo.get)
print(foo.change)
\'\'\'
模块foo--->
111
222
<function get at 0x00000279C9731550>
<function change at 0x00000279C9731040>
\'\'\'
# 强调1:模块名.名字,指名道姓地问某一个模块要名字对应的值,不会与当前名称空间中名字发生冲突

# 强调2:无论是查看还是修改还是其他操作都是以原模块本身,与调用位置无关
import foo
x = 222
foo.change()
print(x)
\'\'\'
模块foo--->
333
222
\'\'\'
# 模块foo
print(\'模块foo--->\')
x = 111
def get(x):
    print(x)
def change():
    global x
    x = 333
    print(x)
4、可以以逗号为分隔符在一行导入多个模块
import time
import foo

import time,foo 不建议

5、导入模块的规范
I:python内置模块
II:第三方模块
III:自定义模块

6、import foo as f # foo=f

7、模块是第一类对象(跟函数一样,可以被其他函数调用,当返回值,参数)

8、自定义模块的命名应该采用纯小写+下划线的风格

9、可以在函数内导入模块
def func():
import foo
   局部变量
10、一个python文件有两种用途
1)、被当成程序运行
2)、被当做模块导入

二 使用模块之from ... import...

1、前面用到的import导入模块在使用时必须加前缀\'模块.\'
优点:肯定不会与当前名称空间中的名字冲突
缺点:加前缀显得麻烦

2、from ... import ...导入也发生了三件事
1)、产生一个模块的名称空间(x,get,change,产生前是在原名称空间,产生模块名称空间后,再指向模块空间的内存地址)
2)、运行foo.py将运行过程中产生的名字都丢到模块的名称空间去
3)、在当前名称空间拿到一个名字,该名称与模块名称空间中的某一个内存地址
from foo import x
from foo import get
from foo import change

print(x)
print(get)
print(change)

3、from...import...导入模块在使用时不用加前缀
优点:代码更精简
缺点;容易与当前名称空间混淆

4、一行导入多个名字(不推荐)
from foo import x,get,change

5、*:导入模块中的所有名字
可以在被导入模块文件中加\'__all__\'=[\'x\',\'get\',\'change\']来控制变量名
from foo import *

6、起别名
from foo import get as g
print(g)

7、模块循环导入问题

 模块循环/嵌套导入抛出异常的根本原因是由于在python中模块被导入一次之后,就不会重新导入,只会在第一次导入时执行模块内代码
 在我们的项目中应该尽量避免出现循环/嵌套导入,如果出现多个模块都需要共享的数据,可以将共享的数据集中存放到某一个地方

三 py文件区分两种用途:模块与脚本

#编写好的一个python文件可以有两种用途:
    一:脚本,一个文件就是整个程序,用来被执行
    二:模块,文件中存放着一堆功能,用来被导入使用


#python为我们内置了全局变量__name__,
    当文件被当做脚本执行时:__name__ 等于\'__main__\'
    当文件被当做模块导入时:__name__等于模块名

#作用:用来控制.py文件在不同的应用场景下执行不同的逻辑,主要用来测试模块
if __name__ == \'__main__\':

四 模块搜索路径

模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块

#模块的查找顺序
1、在第一次导入某个模块时(比如spam),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
    ps:python解释器在启动时会自动加载一些模块到内存中,可以使用sys.modules查看
2、如果没有,解释器则会查找同名的内建模块
3、如果还没有找到就从sys.path给出的目录列表中依次寻找spam.py文件。


#sys.path的初始化的值来自于:
The directory containing the input script (or the current directory when no file is specified).
PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
The installation-dependent default.

#需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。虽然每次都说,但是仍然会有人不停的犯错。 

#在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载。
1 >>> import sys
2 >>> sys.path.append(\'/a/b/c/d\')
3 >>> sys.path.insert(0,\'/x/y/z\') #排在前的目录,优先被搜索
注意:搜索时按照sys.path中从左到右的顺序查找,位于前的优先被查找,sys.path中还可能包含.zip归档文件和.egg文件,python会把.zip归档文件当成一个目录去处理,

#首先制作归档文件:zip module.zip foo.py bar.py 
import sys
sys.path.append(\'module.zip\')
import foo,bar

#也可以使用zip中目录结构的具体位置
sys.path.append(\'module.zip/lib/python\')


#windows下的路径不加r开头,会语法错误
sys.path.insert(0,r\'C:\\Users\\Administrator\\PycharmProjects\\a\')
 

#至于.egg文件是由setuptools创建的包,这是按照第三方python库和扩展时使用的一种常见格式,.egg文件实际上只是添加了额外元数据(如版本号,依赖项等)的.zip文件。

#需要强调的一点是:只能从.zip文件中导入.py,.pyc等文件。使用C编写的共享库和扩展块无法直接从.zip文件中加载(此时setuptools等打包系统有时能提供一种规避方法),且从.zip中加载文件不会创建.pyc或者.pyo文件,因此一定要事先创建他们,来避免加载模块是性能下降。

五 包的介绍

1、什么是包?

#官网解释
Packages are a way of structuring Python’s module namespace by using “dotted module names”
包是一种通过使用‘.模块名’来组织python模块名称空间的方式。

#具体的:包就是一个包含有__init__.py文件的文件夹,所以其实我们创建包的目的就是为了用文件夹将文件/模块组织起来

#需要强调的是:
  1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错

  2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块

2、为何要使用包

包的本质就是一个文件夹,那么文件夹唯一的功能就是将文件组织起来
随着功能越写越多,我们无法将所以功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性

3、注意事项

#1、关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。但对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。

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

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

4、总结包的使用需要牢记三点

1、导包就是在导包下__init__.py文件
2、包内部的导入应该使用相对导入,相对导入也只能在包内部使用,而且...取上一级不能出包
3、
使用语句中的点代表的是访问属性
    m.n.x ----> 向m要n,向n要x
而导入语句中的点代表的是路径分隔符
    import a.b.c --> a/b/c,文件夹下a下有子文件夹b,文件夹b下有子文件或文件夹c
所以导入语句中点的左边必须是一个包

5、 包的使用

绝对导入中执行文件路径找寻

import os

print(__file__)
print(os.path.dirname(__file__))
BAE_DIR = os.path.dirname(os.path.dirname(__file__))
print(BAE_DIR)
path = r\'\\log\\user.log\'.format(BAE_DIR)
\'\'\'
E:/Python学习/python全栈学习/day21/ATM/conf/settings.py
E:/Python学习/python全栈学习/day21/ATM/conf
E:/Python学习/python全栈学习/day21/ATM
\'\'\'

 

绝对导入与相对导入总结

绝对导入与相对导入(看视频软件目录开发介绍)

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

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

Python基础(二十六):模块和包简单介绍

文章目录

模块和包简单介绍

一、模块

1、导入模块

2、制作模块

以上是关于python基础九(模块和包)的主要内容,如果未能解决你的问题,请参考以下文章

Python基础-模块和包

Python基础(二十六):模块和包简单介绍

python基础入门之十八 —— 模块和包

Python基础(二十六):模块和包简单介绍

带你学python基础:模块和包

python基础14 ---函数模块5(模块和包)