Python之路(第十二篇)程序解耦、模块介绍\导入\安装、包

时间:2021-09-11 12:17:27

一、程序解耦

解耦总的一句话来说,减少依赖,抽象业务和逻辑,让各个功能实现独立。

直观理解“解耦”,就是我可以替换某个模块,对原来系统的功能不造成影响。是两个东西原来互相影响,现在让他们独立发展;核心思想还是最小职责,每个地方都只做一件事情;只要一个地方负责了多项事情,就存在解耦的可能。在系统每个层次都可以体现解耦的思想,比如在架构层面把存储和业务逻辑解耦,把动态页面和静态页面解耦;在模块层面把业务模块和统计模块解耦;在代码层面把多个功能解耦等等。

低耦合,高内聚---模块之间低耦合,模块内部高内聚。一个系统有多个模块组成,在划分模块时,要把功能关系紧密的放到一个模块中(高内聚),功能关系远的放到其它模块中。模块之间的联系越少越好,接口越简单越好(低耦合,细线通信)。

二、模块

概念

在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。

使用模块的好处

最大的好处是大大提高了代码的可维护性;其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。

模块的种类

  • python标准库

  • 第三方模块

  • 应用程序自定义模块:自定义模块时要注意命名,不能和Python自带的模块名称冲突。

模块的导入方法

import

import module1

  

import 模块名,一般是导入python的内置模块

import as

  import multiprocessing as mul

  

在之后的代码中就可以直接用mul.方法名了,不用写长长的multiprocessing.方法名

from…import 语句


 from modname import name1[, name2[, ... nameN]]

  

from 模块 import 方法名 ,这个声明不会把整个modulename模块导入到当前的命名空间中,只会将它里面的name1或name2单个方法引入到执行文件里

from…import* 语句

from modname import *

  

这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。大多数情况, Python程序员不使用这种方法,因为引入的其它来源的命名,很可能覆盖了已有的定义。

注意:

模块一旦被导入,即相当于执行了一个.py文件(导入模块所在的文件)里的代码

import的工作机制

import语句导入指定的模块时会执行3个步骤

1.找到模块文件:在模块搜索路径下搜索模块文件

程序的主目录  

PYTHONPATH目录  

标准链接库目录

2.编译成字节码:文件导入时会编译,因此,顶层文件的.pyc字节码文件在内部使用后会被丢弃,只有被导入的文件才会留下.pyc文件

3.执行模块的代码来创建其所定义的对象:模块文件中的所有语句从头至尾依次执行,而此步骤中任何对变量名的赋值运算,都会产生所得到的模块文件的属性(所以自定义函数不要和模块中的名称重合)

不同目录类型的模块文件导入

1、与执行文件同目录模块导入

文件目录结构如下

Python之路(第十二篇)程序解耦、模块介绍\导入\安装、包

Python之路(第十二篇)程序解耦、模块介绍\导入\安装、包

test.py是执行文件,想调用manage.py模块

可以直接用


 import manage

  

或者


 from manage import *

  

2、不同文件目录的模块导入

  M2
├── bin
│   ├── __init__.py
│   └── start.py [程序入口]
├── conf
│   ├── __init__.py
│   └── settings.py
├── core
│   ├── __init__.py
│   ├── accounts.py
│   ├── db_handler.py
│   ├── logger.py
│   ├── main.py
│   └── transaction.py
├── test.py

start.py是执行文件,不同目录下面入口程序得目录加载到sys.path即环境变量中,就可以跨模块调用了

在settings.py 里加入

  import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)

  

这里os.path.abspath(__file__)获取返回settings.py规范化的绝对路径(包含文件),

os.path.dirname(os.path.abspath(__file__))获取当前运行脚本的绝对路径(去掉最后一个文件),

os.path.dirname(os.path.dirname(os.path.abspath(__file__)))获取当前运行脚本的绝对路径(去掉最后一个路径)

注意的一点是:直接用路径添加sys.path.append()添加目录时注意是在windows还是在Linux下,windows下需要‘\’否则会出错。

此时的模块搜索的主目录是 */M2/,即在M2文件夹下搜索

需求1:

mian.py想要引用accounts模块下的函数需要

from core import accounts

也可以这样写

from . import accounts

从当前目录导入模块(但是这里添加的搜索主目录是上级目录,即这个例子的M2文件夹)

需求2:

main.py 想要引用settings模块需要

from conf import settings

需求3:

test.py想要引用logger.py模块需要

from core import logger

from ..proj import hello (待补充)

注意:python使用. .. 相对导入模块要满足两个条件:

1.文件夹中必须有__init__.py文件,该文件可以为空,但必须要有

2.不能作为顶层模块来执行该文件夹中得py文件(即不能作为主函数得入口) 意思:..后不能到主函数入口得目录下

多层目录的模块导入

例子

index.py位置为D:\test_package\a\b\c\index.py

文件目录树

D:.
│ test.py
│ __init__.py

├─a
│ │ __init__.py
│ │
│ ├─b
│ │ └─c
│ │ index.py
│ │ __init__.py
│ │
│ └─__pycache__
│ __init__.cpython-36.pyc

└─__pycache__

  Python之路(第十二篇)程序解耦、模块介绍\导入\安装、包

test.py想要导入index模块需要

from a.b.c import index

  

内置变量: __file__表示当前的文件名

os.path.abspath(path) :返回path的绝对路径

os.path.dirname(path) :返回path的目录(去掉最后一级目录或文件)

例子

index.py文件位置为D:\python\exercise\test_package\b\index.py

在index.py写入

  
  import os
BASE_DIR0 =os.path.abspath(__file__)
BASE_DIR1 = os.path.dirname(os.path.abspath(__file__)) #去掉最后一个文件,返回路径
BASE_DIR2 = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#去掉最后一级目录返回路径
print(BASE_DIR0)
print(BASE_DIR1)
print(BASE_DIR2)
print("这里是index")

  

运行输出结果

  
  D:\python\exercise\test_package\b\index.py
D:\python\exercise\test_package\b
D:\python\exercise\test_package
这里是index

  

if __name__ == '__main__':

一个模块文件可以直接执行或被导入

每个模块都有一个名为__name__的内置变量,此变量值会根据调用此模块的方式发生变化:\1. 如果此文件被作为模块导入,则__name__的值为模块名称\2. 如果此文件被直接执行,则__name__的值为“__main__

我们在创建模块时,在尾部添加如下代码进行模块的自我测试if __name__ == '__main__':

  ...

如果模块被导入,则 if 后的语句就不会执行

安装第三方模块

安装第三方模块有两种方式:

1.通过包管理工具pip完成的

即pip install 模块名或者pip3 install 模块名

注意:Mac或Linux上有可能并存Python 3.x和Python 2.x,因此对应的pip命令是pip3

2.下载源码=> 解压源码=> 进入目录

源码格式大概都是 zip 、 tar.zip、 tar.bz2格式的压缩包。解压这些包,进入解压好的文件夹,通常会看见一个 setup.py 的文件。打开命令行,进入该文件夹。

python setup.py install

  

三、包

包一个文件夹下有多个.py文件,加上__init__空文件,这个文件夹就是一个包了

包是一个有层次的文件目录结构,它定义了一个由模块和子包组成的Python应用执行环境

基于包,Python在执行模块导入时可以指定模块的导入路径 import pack1.pack2.mod1

每个包内都必须有__init__.py文件,可包含python代码,但通常为空,仅用于扮演包初始化、替目录产生模块命名空间以及使用目录导入时实现from*行为的角色