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


    一、程序解耦

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

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

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

    二、模块

    概念

    在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在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、与执行文件同目录模块导入

    文件目录结构如下

     

    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: est_packageacindex.py

    文件目录树

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

      

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

    from a.b.c import index
    

      

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

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

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

    例子

    index.py文件位置为D:pythonexercise est_packageindex.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:pythonexercise	est_packageindex.py
      D:pythonexercise	est_package
      D:pythonexercise	est_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*行为的角色

     

  • 相关阅读:
    python:HTML转义
    Python 安装 MySQLdb
    C# 获取当前路径方法
    配置 vim Python IDE 开发环境
    python:HTML转义
    Python list去重
    源码探秘
    加号的作用
    多态练习
    在web service用Cache要导入System.Web.HttpRuntime
  • 原文地址:https://www.cnblogs.com/Nicholas0707/p/9003488.html
Copyright © 2020-2023  润新知