python 模块,包及其相关用法

模块

什么是模块

在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里面,代码会越来越长,越来越不容易维护。

为了编写可以维护的代码,我们把很多函数分组,分别放到不同额文件,这样,每个文件包含的代码就相对比较少,很多编程语言都采用这种组织代码的方式。在python中,一个.py文件就称之为一个模块。

使用模块的好处

1,最大的好处就是大大的提高了代码的可维护性,其次,编写代码不必从零开始,当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括python内置的模块和来自第三方的模块。

2,使用模块还可以避免函数名和变量名之间的冲突,每个模块有独立的命名空间,因此相同名字的函数和变量完全可以分别存在不同的模块中,所以,我们自己编写模块时候,不必考虑名字会和其他模块冲突。

模块的分类

模块分为三种:

  1. 内置标准模块(又称为标准库),执行help(‘modules’)查看所有python自带模块列表
  2. 第三方开源模块,可以通过pip install modules 联网安装
  3. 自定义安装

如何导入模块

模块调用的方法

  1. import module
  2. from module import xx
  3. from module.xx.xx import xx as rename
  4. from module.xx.xx import *
    注意:模块一旦被调用,即相当于执行了另一个py文件里面的代码

在Python 中用关键字import来导入某个模块:

   import  modname       

比如要导入模块numpy,就可以在文件最开始的地方用import numpy 来引入。在调用numpy模块的函数时,必须这样引入:

模块名.函数名(比如:import numpy numpy.arange(5))

与第一种方法的区别是:funcname被直接导入到本地名字空间取了,所以他可以直接使用,而不需要加上模块名的限定 * 表示,该模块的所有公共对象(public objects)都被导入到当前的名称空间,也就是任何只要不是以 “_” 开始的东西都会被导入。

为什么必须加上模块名这样调用呢?
因为可能存在这样一种情况,在多个模块下含有相同名称的函数,此时如果只是通过函数名来调用,解释器无法知道到底要调用那个函数,所以如果像上述这种情况引入模块的时候,调用函数必须加上模块名。

有时候我们只需要引入模块中的某个函数,只需要引入该函数即可,此时通过下面语句实现:

    from modname   import    funcname      

(from modname import fa,fb,fc

from modname import * 但是这个得谨慎使用 )

当然可以通过通过这种方法不仅可以引入函数,还可以引入常量,通过这种方式引入的时候,调用函数时只能给出函数名,不能给出模块,但是当两个模块中含有相同名称函数的时候,后面一次引入会覆盖前一次引入。所以有以下建议:
1) 如果你经常访问模块的属性和方法,且不想一遍又一遍的敲入模块名称,使用 from module import

2) 如果你想要有选择性地导入某些属性和方法,而不想要其他的,使用 from module import

3)如果模块包含的属性和方法与你的某个模块同名,你必须使用 import module 来避免名字冲突

4)尽量少使用 from module import *,因为判定一个特殊的函数或属性是从哪里来的有些困难,并且会造成调试和重构都更困难。

模块查找路径

初学者会发现,自己写的模块只能在当前路径下的程序里面才能导入,换一个目录再导入自己的模块就报错了,,这是为什么呢?

答案就是:这与导入路径有关
在这里插入图片描述

所以python解释器就会按照列表顺序去依次到每隔目录下去匹配你要导入的模块名,只要在一个目录下匹配到了该模块名,就立马不继续往下找,如果找完了依旧没有找到,那么就会报错。

(注意,可能是linux下,列表的第一个元素为空,即代表当前目录,所以你自己定义的模块在当前目录会被优先导入)

模块的调用

首先举个例子:

def  main()   
    pass 
mian()

如果直接在模块里面调用这个函数,那么,假设其他模块需要import当前模块,那么这个程序也会执行,但是其他模块想要的只是import而已,所以显然,这样是不可取的,我们需要将这种调用方式改成下面这种。

if __name__  == '__main__':   
    main()

这样的话,只有当前模块被执行的时候,这个函数才被调用,程序才执行。

当你的模块文件越来越多的时候,就需要对模块文件进行划分,比如把负责跟数据库交互的都放在一个文件夹,把页面交互相关的放在一个文件夹。
在这里插入图片描述

不同的包之间如何相互导入?

包就是文件夹,但该文件夹下必须存在 init.py 文件, 该文件的内容可以为空。int.py用于标识当前文件夹是一个包

from crm import views 
views.sayhi()

其中crm/views.py内容如下:

def sayhi():   
   print('hello world!')

跨模块导入包

在这里插入图片描述
根据上面的结构,如何实现在crm/views.py里导入proj/settings.py模块?

如果直接像上面这样导入:

from proj import views

结果:Traceback (most recent call last): File “D:/crm/views.py”, line 1, in from proj import viewsModuleNotFoundError: No module named ‘proj’

为什么跨模块直接导入会报错呢?
是因为路径找不到,proj/settings.py 相当于是crm/views.py的父亲(crm)的兄弟(proj)的儿子(settings.py),settings.py算是views.py的表弟啦,在views.py里只能导入同级别兄弟模块代码,或者子级别包里的模块,根本不知道表弟表哥的存在。
这可怎么办呢?

答案是添加环境变量,把父亲级的路径添加到sys.path中,就可以了,这样导入 就相当于从父亲级开始找模块了。crm/views.py中添加环境变量

crm/views.py中添加环境变量

crm/views.py中添加环境变量
在这里插入图片描述

绝对导入和相对导入

在这里插入图片描述
在这里插入图片描述

其实这两个错误的原因归根结底是一样的:在涉及到相对导入时,package所对应的文件夹必须正确的被python解释器视作package,而不是普通文件夹。否则由于不被视作package,无法利用package之间的嵌套关系实现python中包的相对导入。文件夹被python解释器视作package需要满足两个条件:

  1. 文件夹中必须有__init__.py文件,该文件可以为空,但必须存在该文件。
  2. 不能作为顶层模块来执行该文件夹中的py文件(即不能作为主函数的入口)。

所以这个问题的解决办法就是,既然你在views.py里执行了相对导入,那就不要把views.py当作入口程序,可以通过上一级的manage.py调用views.py
在这里插入图片描述
但把from …proj import settings 改成from . import models 后却执行成功了,为什么呢?from … import models会报错的原因是,这句代码会把manage.py所在的这一层视作package,但实际上它不是,因为package不能是顶层入口代码,若想不出错,只能把manage.py往上再移一层。

正确的代码目录结构如下
在这里插入图片描述
注意:虽然python支持相对导入,但对模块间的路径关系要求比较严格,处理不当就容易出错,so并不建议在项目里经常使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值