模块、包、目录规范与模块编写规范

2022/9/13 23:19:32

本文主要是介绍模块、包、目录规范与模块编写规范,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

模块、包、目录规范与模块编写规范

一、什么是模块?
   模块分三大类 
       1、内置模块,python自带的
       2、第三方模块,别人写的,发布到网上的,pip导入的那种
       3、自定义的模块,自己写的一个py文件就是一个模块,,m.py文件,这个m就是一个模块
            自己写的一个文件夹,也是这一个模块
    文件名:foo.py   模块名foo
   模块的4种形式:
       1、使用python写的.py文件
       2、已经被编译为共享库或者dll的c或者c++扩展
       3、把一系列模块组织到一起的文件夹(注:文件夹下一定有一个__init__文件),读这个文件夹就是读这个文件
        就是包,,pickage
       4、使用c编写并链接到python解释器的内置模块

二、为什么要用模块?
    1、内置与第三方模块可以拿来就用,不用再造轮子,可以极大的提升效率。       
    2、自定义的模块:可以将程序的各部分功能提取出来,放到一个模块中,供大家共享使用。
        好处是减少了代码冗余,使程序组织结构更加清晰。
        
三、如何用?
    1、import foo   #  这里的run是foo.py的名字,是run
        实际上就是导入这个foo.py文件
    2、首次导入模块会发生三件事:
        1、执行foo这个文件
        2、运行foo.py这个文件,将这个文件产生的所有变量名字都丢到叫foo的名称空间。
        3、在当前文件中产生一个名字叫foo,该名字的内存地址指向2中叫foo的名称空间。
    
    3、 首次导入会发生这三件事,再次导入时,都是引用第一次导入的内容。不会重复执行代码。
        
    4、引用:
        强调1:指名道姓的问某一个模块要名字对应的值
        如:import foo 
            foo.f1.()   # 执行foo.py中的f1()
        强调2:无论是查看还是引用,都是以原模块为准,与调用位置无关
             也就是调用的都是原模块的设置与变量值。
    5、导入模块格式
        如下:
        import time
        import random
        import os
        
        不要这样import time, datetime, random, os, sys,,乱
    
    6、导入模块规范
        导入顺序:
        1、python内置模块
        2、第三方模块 
        3、程序员自定义模块 
    
    7、import。。。 as ... 可以为导入的模块起个别名
       如:
       import foo as f
       调用: f.f1()
    
    8、 函数是第一类对象,即函数可以当成变量去用,可被赋值,可当参数,可当成返回值,可当容器的元素
       模块也是第一类对象
       
    9、模块的命名
       纯小写,与变量名的命名规则一致
    
    10、导模块可以在开始位置导入,可以函数内部导入。    

二、 一个python文件有几种用途?  执行py文件 与导入py文件有什么区别?
    一个py文件有两种用途            
        1、被当作程序运行
        2、被当作模块导入
            
    二者的区别?
    被当作程序运行的时候,运行完后,内存即回收
    被当作模块导入时,只有在引用者关闭、del的时候,内存才被回收
    
    每个py文件都内置了一个属性变量叫'__name__'。
    当foo被运行时,'__name__'的值为'__main__'
    当foo被当做模块导入时,'__name__'的值为”foo“
    
三、from...import ...
    与import 有什么区别?
    1、import导入模块,使用这个模块的功能时,必须加import前缀
      random.randint()
      优点:肯定不会与当前名称空间中的名字冲突
      缺点:加了前缀,显得很麻烦
    
    2、from...import...执行的时候,也发生三件事
        运行foo
        产生一个名称空间,放入产生的变量
        在当前名称空间拿到一个名字,该名字指向导入模块名称空间中的某一地址。
          --当一个函数内定义global变量,例如函数前x=1 ,函数中global定义x=2
          那么在这个函数没被调用时,x是1。
          这个函数被调用后,再调用x就变成了2
      from。。。import。。。导入,使用时,不用再加前缀
        优点:代码更精简
        缺点:容易混淆
        
    3、不推荐 from foo import x, f1, get, change
    4、不推荐 from foo import *  非常容易混淆  变量与函数
    5、了解: __all__
      每个py文件或者模块都有一个内置变量叫__all__,是一个列表,里面记录了本模块或者本文件所有的字符串名字。
      from foo import *,,,,这个导入*,也就是导入全部__all__里面的所有名字
      控制*代表的名字有哪些    
    6、起别名
        import time as t
        from foo import change as c
        
        
四、循环导入问题
    编写程序,如果两个模块之间交叉互相引用,这是一种非常垃圾的设计,极易瘫痪。
    如果实在是有需要,可以利用导入时不执行代码的特点,把交叉引用的东西,放到一个函数内部。
      如: def f2():
              from foo import f1
              。。。
    这种解决方案叫做”屎上雕花“
    


五、搜索模块的路径与优先级
    无论是import 还是from ..import ,在导入模块时都涉及到查找问题
    优先级:
        1、内存(内置模块)
        2、按照sys.path中存放的文件的顺序依次查找要导入的模块
    import sys
    执行print(sys.path)
    sys.path的值是一个列表,存放了一系列的文件夹
    其中,第一个文件列是当前执行文件所在的文件夹
    了解:sys.modules可以查看当前已经加载到内存中的模块
    print(sys.modules)可以查看当前加载的模块
    了解:
    import foo
    del foo
    此时查看内存中的sys.modules,可以看到foo路径还在内存中,这是python的内存优化机制
    为什么没有删除,因为模块是全局的,很可能还会继续使用,或者其他地方还会调用,如果再调用的时候,直接从内存中调用会更加快捷。
    首次导入,一定会是从硬盘找。
    如果当前文件夹没有,内存也没有,怎么办?
    先执行sys.modules.append(r'要导入模块的绝对路径')
    然后再执行import 模块名称

六、区别py文件的两种用途
    被当作程序运行的时候,运行完后,内存即回收
    被当作模块导入时,只有在引用者关闭、del的时候,内存才被回收
    
    被当作程序运行与被当作模块导入的区别。
    每个py文件都内置了一个属性叫'__name__'。
    当foo被运行时,'__name__'的值为'__main__'
    当foo被当做模块导入时,'__name__'的值为”foo“    

七、如何编写一个规范的模块 
    1、如果你的工作是要写一个模块的话,请在第1行加入注释说明,写明本模块的功能与描述
    2、再导入其他模块 ,每个导入后面最好也加入描述
    3、再定义全局变量,如果不是必须的,最好使用全局变量。后面加注释说明
       全局变量的使用要慎重,可能会被别人把值修改掉。最好是都使用局部变量最好。独立性最好,不易被影响。
    4、再定义类。  加注释文档说明
    5、再定义函数。 函数内要跟上文档注释。
    6、if __name__ == '__mail__':
        开始主程序
    
       
       
八、包(有__init__的文件夹)  重要
    1、什么是包?
      包就是一个包含__init__.py文件的文件夹
    2、为何要有包?
      包的本质是模块的一种形式,包是用来被当做模块导入。
      当导包(文件夹)的时候,有一个文件可以代替运行执行(运行包、创建名称空间、导入文件创建变量名称)。
      包里面的所有文件功能,都被包含在__init__中。
    可以将一个文件夹做成一个模块,导模块就是在导文件夹,就是在导__init__
    包的作用就是为了导入,连同下面的文件。不是为了本身运行。
    可以把多个文件夹,多个包,都组织到一个文件里面使用。
    
    了解:python3,如果包里面没有__init__,不会出错。python2会出错。
    被导入 和 被运行执行 ,是截然不同的两件事。
    
    包可以规范有序的整理模块的功能,包可以把不同的功能放在不同文件分别管理,以升级、管理 、维护提供方便。
    
    3、绝对导入与相对导入
    绝对导入:
    包的导入,强调三点:
        1、站在模块设计者的角度,无论是import,还是from。。import,可以带. 
            如:from foo.m1  import f1
            点的左边,必须是一个包,否则非法
            可以带一连串的点,如:import 顶级包.子包.子模块
        2、包A 和 包B 有同名模块,导入后也不会有冲突。
            如A.a 和 B.a 来自两个名称空间
        3、import导入文件时,产生名称空间中的名字来源于文件。
           import包,产生的名称空间的名字同样来自于文件。即包下的__init__.py
    
    相对导入: 仅限于包内,不能跨出包。
        包内的导入,推荐使用相对导入。
        包外的导入,推荐使用绝对导入。
    import os
    import sys
    sys.path.append(os.path.dirname(os.path.dirname(__file__))
    这条命令会取得当前文件夹的父级目录,并追加到sys.path中。
    from core.src import run 然后即可从core包的src模块,导入run函数。
    


九、软件开发的目录规范
    ATM---》 系统文件夹名称
        bin  放启动文件  
        conf  配置文件,放帐号密码文件的  日志文件路径 等
        db   数据库相关,对数据库读写操作 ,注册用户 读写表的数据,数据交互
        lib  存放程序中常用的自定义模块 
        core 放最核心代码的逻辑  src.py
        api  与外部数据的接口,接口主要用于业务逻辑提供数据操作。
        log  存放日志文件
        -----上面是包,下面是文件
        run.py  程序启动文件,一般放在根目录。因为运行时会默认将运行文件所在的文件夹作为sys.path的第一个路径,这样就省去了处理环境变量的步骤。
        setup.py  安装、部署、打包的脚本
        requirements.txt   存放软件所需要依赖的外部python包的列表
        readme  项目说明文件
    
    代码文件规范
        声明‘utf-8’
        本模块说明注释
        导入其他模块
        定义全局变量---越少越好,越少越不容易出问题
        定义类
        定义函数
        if __name__ == __main__  
            run()
            
        -------------
        import os
        import sys
        sys.path.append(os.path.dirname(os.path.dirname(__file__))
        这条命令会取得当前文件夹的父级目录,并追加到sys.path中。
        from core.src import run 然后即可从core包的src模块,导入run函数。
        


十、补充函数的知识点
    类型提示:type hniting
    def register(name: str, age: int, hobbies: tuple):
        print(name)
        print(age)
        print(hobbies)
        return ...
    python定义函数的时候,变量参数是可以传入任何类型的。想传整数而实际传入字母,浪费时间,有个提示的话,更有效率。
    C java 把程序员当驴, python把程序员当人,是会犯错误的
    def register(name: str, age: "这里要写数字憨批", hobbies: tuple):
        print(name)
        print(age)
        print(hobbies)
        return ...
    
    print(register.__annotations__)  # {'name': <class 'str'>, 'age': '这里要写数字憨批', 'hobbies': <class 'tuple'>}


'''



这篇关于模块、包、目录规范与模块编写规范的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程