摘要:

一.模块:

  1. 模块实质上就是一个以.py结尾的文件,可以被其他py文件调用;
  2. 使用模块:大大提高了代码的可维护性;编写代码不必从零开始;当一个模块编写完毕,就可以被其他地方引用!
  3. 导入模块时,会去python的默认搜索路径中寻找:
- python的默认搜索路径sys.path;
- 添加自定义的搜索路径时,sys.path是一个列表;
[sys.apth.append("path"),sys.path.append("/home/kiosk/1-Pythonv3/day08/code") ,sys.path.insert(0,'/home/kiosk')]
  • 导入一个模块的实质是将模块的文件重新运行一次:

在桌面上写一个名为happy.py的模块,由于没有/home/kiosk/Desktop的路径,所以无法加载模块,添加路径后,可以加载自定义模块;如有两个相同命名的模块,先执行路径在前面的,也可以调整路径的顺序!

  • 导入模块的方法:
- import module1,module2- from 模块名 import 函数名- from 模块名 import 函数名 as 函数别名- import 模块名 as 函数别名

二.包

  1. 导入一个包的实质是运行包里面的__init__.py文件;
  2. 导入包的方法:
- import 包名.模块名 - from 包名 import 模块名 - import 包名(注意__init__.py函数的内容)

- 第一种 from 包名 import 模块名,不用在包里的__init__写入 import 模块名;

- 第二种 import 包名,需要在包里的__init__写入 import 模块名!

1.要解决的问题

Python在语义中存在着模块(当然还有函数)这几个概念。

在编写Python代码时,我们需要管理代码的文件目录结构

这时候会遇到这样一种情况:

1.由于Python一个文件一个模块一个带__init__.py的目录算一个

2.而为了控制代码文件不要过大,我们需要的是一个类(几个类或加些许函数)分配一个文件

3.这时候会出现类似这样的语句:

#第一种
import package_a.class_a_file as caf
a = caf.ClassA()#第二种
form package_a.class_a_file import *
a = ClassA()#另外几种就不意义列举了...

以上除了直观上可以看出import过长外,隐藏的另一点是我们是希望一个类一个文件,在使用多个相关类的时候就必须写很多import。(注:我们可不想一堆代码扎堆,弄出一个超大代码文件。)

2.解决方案要达到的效果

#文件目录结构
#|--demo.py
#|--package_a
#   |--__init__.py
#   |--class_a.py  #类ClassA
#   |--class_b.py  #类ClassB和函数func_b()#demo.py中可以直接使用
from package_a import *a = ClassA()
b = ClassB()
func_b()

由于Python里一个带__init__.py的目录算一个包,所以利用这一机制,把类文件放在包里,用包来管理类。

注:在Python里“包是模块,而模块不是包”。用system.modules可以取到的名字是包和模块都有的,而用__package__却能很好的区分包和模块。也就是“包其实是一种特殊的模块”。

3.解决方案

这就是解决方案的文件base.py,代码很短:

import sys_packet_ = {}#它是个装饰器,item是类,或者函数
def export(item):#获取item的模块对象module = sys.modules[item.__module__]#由模块对象得到包对象package = sys.modules[module.__package__]#把item添加到包的__dict__里package.__dict__[item.__name__] = item#生成所有使用该解决方案的包的__all__变量,并把导出的item添加进去if not package.__name__ in _packet_:_packet_[package.__name__] = []_packet_[package.__name__].append(item.__name__)#原封不动地把item返回return item#它是个函数,在包__init__.py里用于获取__all__
def packet(name):if not name in _packet_:_packet_[name] = []return _packet_[name]

代码用意我写在注释里了,就是以装饰器来把类添加到包的__dict__和__all__里。__all__需要利用packet在包里生成,不这么做只会使得from package_name import * 后不能找到类,需要写具体的类名from package_name import ClassA。

4.使用解决方案

先来看下使用解决方案后的目录结构:

#文件目录结构(使用后结构只多了base.py)
#|--base.py
#|--demo.py
#|--package_a
#   |--__init__.py
#   |--class_a.py  #类ClassA
#   |--class_b.py  #类ClassB和函数func_b()

代码处就需要做到以下几点:

1.关于被导出的类文件里应该怎么做,这里以class_b.py为例子:

# ./package_a/class_b.py#1.需要导入base
import base#2.使用export装饰器,装饰要导出的类或函数
@base.export
class ClassB:pass#2.同样的export可以导出函数
@base.export
def func_b():print('func_b')

2.修改package_a包__init__.py文件:

# ./package_a/__init__.py#1.导入base
import base#2.导入将要导出的子模块,需要具体模块名字的形式,from . import * 不可用
from . import class_a,class_b#3.用packet初始化__all__,这个可选,主要是看要不要支持 from 的用 * 导入
__all__ = base.packet(__name__)#4.这个是可选的,因为如果用了__all__会影响from *。可以用export把__init__.py里的项,加入__all__
@base.export
def pafunc():print('pafunc')

5.总结

使用该解决方案可以归纳为两点:

1.用@base.export标记要导出的类或函数

2.在包__init__.py里初始化__all__ = base.packet(__name__)

3.(说好的只有两点呢?)其实第2点是可选的,不过最好加上。而在包的__init__.py里导入子模块才是真正的第2点。不然子模块不会被载入,也谈不上导出了。

最后,demo.py里可以这么写,和预期的效果一样:)

# ./demo.pyfrom package_a import *a = ClassA() # 上面的实例没有给出,不过假设有ClassA在class_a.py里的
b = ClassB()
func_b()

Python 包、模块、类以及代码文件和目录的一种管理方案相关推荐

  1. python安装os模块_python的os模块(ipython,文件,目录,权限,管理)

    什么是os模块 os模块提供了多数操作系统的功能接口函数.当os模块被导入后,它会自适应于不同的操作系统平台,根据不同的平台进行相应的操作,在python编程时,经常和文件.目录打交道,这时就离不了o ...

  2. ipython使用oracle,python的os模块(ipython,文件,目录,权限,管理)

    什么是os模块 os模块提供了多数操作系统的功能接口函数.当os模块被导入后,它会自适应于不同的操作系统平台,根据不同的平台进行相应的操作,在python编程时,经常和文件.目录打交道,这时就离不了o ...

  3. python xlrd读取excel-使用Python xlrd模块读取Excel格式文件的方法

    这是一篇关于如何使用Python xlrd模块读取Excel格式文件的方法的文章,下面的python代码中使用 了xlrd模块的方法,这样就能够很方便的读取 excel 文件内容.同是这个xlrd模块 ...

  4. 关于压缩jar包时提示*.*没有这个文件或目录的问题以及解决办法:

    关于压缩jar包时提示.没有这个文件或目录的问题以及解决办法: 问题描述: 我在打包jar时,CMD中进入到包的上一层目录. 在命令提示符中输入 提示如下: 从提示中可知没有找到我们想要打包的clas ...

  5. c语言是以文件为单位编译,c语言从头开始(三:编译器工作原理) (我们还可以自己编写头文件后缀是xx.h并把它当前代码文件所在目录我们要用就可以直接通过下面代码使用)...

    c语言从头开始(三:编译器工作原理) [[枫歌枫歌]c语言从头开始(三:编译器工作原理)]https://toutiao.com/group/6568056688174170628/?iid=1590 ...

  6. /usr/bin/python^M: 解释器错误: 没有那个文件或目录

    [1]问题现象 执行python脚本,提示错误:/usr/bin/python^M: 解释器错误: 没有那个文件或目录 [2]原因分析 大多数是因为脚本文件在windows下编辑过.在windows下 ...

  7. python怎么实现输入多行文字_介绍一个Python 包,几行代码可实现 OCR 文本识别!...

    点击上方 Z先生点记,加为星标 第一时间收到 Python 技术干货! 文字 OCR 识别技术现在已经相当成熟了,无论 其 准确度还是识别速度 都能够满足我们的日常需要:今天给大家介绍一个 Pytho ...

  8. Yamale Python 包受高危的代码执行漏洞影响

     聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 YAML 的机构和验证工具 Yamale 中存在一个高危的代码注入漏洞,可被攻击者用于执行任意 Python 代码. 该漏洞的编号是CVE-20 ...

  9. python的模块提供了许多文件处理方法_详解使用Python处理文件目录的相关方法

    所有文件都包含在各个不同的目录下,不过Python也能轻松处理.os模块有许多方法能帮你创建,删除和更改目录. mkdir()方法 可以使用os模块的mkdir()方法在当前目录下创建新的目录们.你需 ...

最新文章

  1. 控制文件的多路复用技术
  2. svn服务器如何导入导出文件,如何导入svn dump备份文件或源代码文件?
  3. 手机控制树莓派linux,怎样用PC或手机远程控制树莓派
  4. Linux 下的文件管理管理系统中的输出输入
  5. 核心频率个加速频率_仅少数Ryzen 9 3900X能摸到官方最大加速频率,其他处理器也有这问题...
  6. 约数研究问题的算法优化和推导证明(洛谷P1403题题解,Java语言描述,含Latex公式编辑知识)
  7. Java字符串操作及处理
  8. Qt网络编程实现TCP通信
  9. FPGA 429 接口设计
  10. Photosho cs6安装字体教程
  11. 手把手带你搭建Linux环境(保姆级,包含vivado与petalinux)
  12. html调用网易云播放器无法自动播放,网页内嵌网易云插件全程(包括生成自己歌单的外链)...
  13. express静态文件
  14. 关于H5请求数据报跨域问题记录
  15. python adb读取手机中短信_python+adb实现自动化获取手机信息
  16. 阿里p8整理的这套K8S手册,我看谁还没有看过
  17. Windows11 右键卡顿
  18. 东方财富通快捷键一览
  19. 2017年、2019年全国大学生电子设计竞赛综合测评——常用电路Multisim仿真——方波、三角波振荡电路
  20. CANopen通信之NMT通信

热门文章

  1. 微人事项目视频教程已经开始更新,国庆节有事情做啦!
  2. 中职学校计算机专业宣传口号,中职学校宣传标语
  3. Event事件-1:addEventListener事件监听 / 事件冒泡事件捕获 / 事件委托 / preventDefault 阻止默认行为 / cancelBubble、stopPropa...
  4. 解决linux重新启动时有线网络连接不上
  5. python-numpy--矩阵与数组的操作
  6. 火法冶炼高冰镍制电池级硫酸镍除硅
  7. 五分钟搞定 HTTPS 配置,二哥手把手教
  8. 滴滴出行平台业务架构演进
  9. 二手车交易价格预测(一)
  10. 我的浙大MEM上岸经验分享