:Python项目组织结构-第一节:包模块以及__init__.py文件

Posted 快乐江湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了:Python项目组织结构-第一节:包模块以及__init__.py文件相关的知识,希望对你有一定的参考价值。

文章目录

本章主要叙述Python项目的组织结构,这一章内容非常重要(很多人学完Python之后竟然连模块的含义都解释不清)

大型的、复杂的软件项目是不可能只用一个.py文件就完成的,就像人员组织一样,它是由很多复杂的模块构成的。


一:Python项目组织结构

(1)Python项目组织结构

  • 以下说法其实并不准确,但是在很多情况下我们都是这样理解的(说白了就是他们在你眼中展示的样子

Python项目的组织结构从上至下依次为

  • 包(package):只要文件目录下,包含_init_.py这个空文件,Python解释器就会认为这个目录是一个包。这就是包和文件夹的显著区别
  • 模块(module):任意一个*.py的Python脚本文件就是一个模块
  • 类(class):面向对象思想,而且建议一个模块只包含一个类
  • 函数、变量

(3)包与模块的作用

在python交互式解释器中操作输入的代码,在退出python时是不会被保存的; 而模块文件中的代码是永久存在的。减少重复代码, 减少工作量(写的量、改的量)、代码更优雅、拿来主义

  • 比如数据分析经常会用到的,Numpy、Pandas等,这些模块中的代码我们也是可以实现的(难度很大),但不如直接用现成的方便

(2)包与模块的名字

不同的包下面可以有相同名字的模块,区别他们时使用“包名.模块名”

二:导入模块

因此,要使用其他模块内的变量或方法时,就需要导入相应模块,并且在引用时也要以“模块名.变量名”或“模块名.方法名”的方式引用

(1)import

import导入模块格式如下

import module1[, module2[,... moduleN]

如下,在p1.py文件中有变量a = 10;同时,test.py文件和p1.py处于同一包内,所以这里很容易导入


如果test.py文件和p1.py不在同一包内呢?如下,此时导入时就要以“包名.模块名”的方式导入了,同时使用时也要以“包名.模块名.变量名”或“包名.模块名.方法名”的方式使用


当模块嵌套过深时,引用变量就会变得很臃肿,此时可以使用import...as... 语句进行命名,这样在引用时就可以直接使用别名了

(2)from…import

Python 的 from...import 语句让你从模块中导入一个指定的部分到当前命名空间中,import后面可以是变量、方法或者是模块


如果在import后面跟上通配符*,那么就会把模块中所有内容导入

但是这种方式缺陷也很大,因为导入时十分不明确。因此在这种情况下,我们可以使用模块内置属性__all__,去设定被导入模块在被导入时哪些变量可以被导入

  • 关于模块的内置属性在后面会细谈

例如,如果只想要变量ac在遇到通配符*时被导入,那么在该模块最前面加入

__all__ = ['a', 'c']

执行后会发现,变量ac正确打印,但变量b却显示异常

三:init.py文件

(1)作用

Python的包下面有一个特殊__init__.py文件,它的作用有点像构造函数(类在被实例化时自动调用)。具体来说就是,当一个包被导入时,会自动执行__init__.py文件

这里我们可以验证一下,具体流程如下

  • test.py文件和包one平级的,包one下面有__init__.py文件和p1.py文件
  • __init__.py文件中加入a = "this is a __init__文件"并打印
  • 然后在p1.py文件中给变量b赋值为10
  • 最后在test.py文件中导入p1.py并打印b
  • 你会发现不止变量b被打印了,而且__init__.py中的a = "this is a __init__文件"也被打印了
  • 这表明在包被导入的时候,__init__.py会自动执行

(2)使用场景

①:前面说过,__all__可以决定本模块内的那些变量被导出,同样,__all__如果放置在__init__.py文件中就可以决定本包内哪些模块被导出

这里可以验证下,流程如下

  • __init__.py文件中不写任何东西
  • one下面的p1.pyp2.py中分别有变量a=10和变量b=20
  • test.py文件中写入from one import *表示导入包one下的所有模块
  • 然后执行,你会发现无法打印

  • 此时如果在__init__.py中加入__all__ = ['p1'],就表示只把p1.py文件导入
  • 执行后你会发现结果和预期设想的一样


②:__init__.py也经常会用于批量导入包。有的时候有些模块是要经常使用的(比如一些常见的Python内置库),在这种情况下,如果在每个文件中都重复写一遍,难免繁琐,所以可以把这些需要重复导入的模块的语句放置在一个包的__init__.py中, 之后想要使用时,只需要导入该包即可

  • 引用时,注意命名空间

四:关于包和模块一些注意点

  • 如果之前没有任何编程语言基础,那么对这一部分你可能会感觉很乱,而且这部分也经常会导致一些错误发生

①:包和模块不会被重复导入

②:避免循环导入

下面就是一个循环导入的例子,执行p1时遇到了import p2,进入p2后又遇见了import p1,然后又进入p2。这样就形成了循环

③:模块被导入时模块里面的语句是会被执行的

  • 这一点很多人没有注意到
  • 这一点其实经常用于入口文件

以上是关于:Python项目组织结构-第一节:包模块以及__init__.py文件的主要内容,如果未能解决你的问题,请参考以下文章

python基础4

库包模块

翻译:《实用的Python编程》09_01_Packages

皇甫?Struts_第一节课

包和模块

Python模块详解以及import本质,获得文件当前路径os.path.abspath,获得文件的父目录os.path.dirname,放到系统变量的第一位sys.path.insert(0,x)