博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python 中的模块和包
阅读量:6438 次
发布时间:2019-06-23

本文共 4667 字,大约阅读时间需要 15 分钟。

原文引至:

对于python中的模块和包, 我简直就想说, js nmlgb 就是一个 trash... 在前端写js根本就没有什么模块和包, 全部都是全局... 真lj...

畅快了. 写了这么久的js, 连内部的模块的包都搞的这么复杂... 艹...

在python中, 已经定义好了完美的模块和包的引用机制.
我们先来看看Module

Module

在python中, 模块实际上,就相当于与业务逻辑解耦的可重用的一些函数方法. 所以, 我们可以预先定义一个模块:

// 命令为sam.pydef add(a,b):    return a+b

之后在同目录中,打开一个 Terminator.

接着输入:

>>> import sam>>> sam.add(1,2)//结果为:3

实际上, 这就是一个简单的模块. 但,当我们导入的时候, 会在Module的目录中生成一个.pyc文件, 该其实就是用来对Module进行缓存,并编译为Binary 文件, 以便py以后再次引入.

现在, 我们已经学会如何写入Module,引入Module. 这里,我们需要更进一步去探索, python是如何进行Module Path的搜索的.

模块路径搜索

在nodeJS中, 他的搜索方式是, 先看内部定义的Module 有没有. 没有的话,则会开始寻找每一层的node_modules. 然后在里面搜索你的文件.js

那么在py中,他是怎样一个过程呢?
py将搜索路径,放在了sys.path中.我们可以查看一下. sys.path里面的内容.

import syssys.path

然后就会出现, 一些路径,比如这个:

['','C:\\Python33\\Lib\\lib-dynload','C:\\Windows\\system32\\python33.zip','C:\\Python33\\DLLs','C:\\Python33\\lib','C:\\Python33\\plat-darwin','C:\\Python33\\lib\\site-packages']

可以看到, 第一个为空, 他实际代表的就是current directory.

具体的顺序是:

  • 当前目录

  • sys.path定义的相关目录

  • 安装依赖的目录

所以, 如果你想自定义自己的Module 直接添加在sys.path里面即可.

那应该怎样进行添加呢?
实际上, 这就是查找关于sys.path的方法了. 还记得help()吗?
查找后,我们基本上都会明白了. md, 这不就是list吗?
那剩下的不就是调用,list的方法进行添加和删除吗?
一般而言,python的工作目录是放在对应的pythonLib文件夹内.这里,我将我常用的py 模块路径添加进去

sys.path.append('/Users/jimmy_thr/Documents/pythonLib')

之后, 我只要将我写好的Module 放在指定的文件内即可.

模块进阶

上面, 我们只是学会使用基本的Module 导入, 实际上,py提供了 更加丰富的Module statement.

比如, 重命名, 指定导入, 全导入

Module rename

这个算是一个py Module的一个附加值吧.

具体用法很简单.

import sam as sbsb.add(1,2)

就酱, 实际上,就是使用as将模块的名字换一个. 并且, 换了之后sam, 也就不存在了.

Specific Module

直接看demo吧:

//直接导入 add方法from sam import add// 也可以导入多个from sam import add,minus

这样导入的结果也是, 不能使用sam.

如果你想, 将module里面所有的方法都导入的话, 直接使用* 即可

from sam import *

不过, 真强烈不建议这么做. 因为, 并没有什么卵用, 并且, 万一出现什么bug, 都不知道这个方法哪来的.

Module complement

在nodeJS中, 他的模块引用是值引用类型, 即就是, 一次引用之后, 就会放在缓存里面, 以后如果在引用的话, 会直接从缓存里面取了.

看一个demo:

def add(a,b):    return a+bprint(add(1,2))//接着,我多次引用>>> import sam3>>> import sam

只会出现一次, 说明, sam Module 只能导入一次. 其余的就 nonesense. 但是,如果你的模块是内部循环型的, 那这样不就go die了吗?

hehe ~ py 早教看到这一点了, 在内置的中提供了reload方法, 来帮助我们实现, 模块的引用更新

>>> import imp>>> imp.reload(sam)3

最后在补充一个dir(module)方法. 他的作用,就是用来查看指定Module当中的全局变量和函数名.

>>> dir(sam)['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'add']

其余的用underscore来连接的, 是py中 module的一部分. 比较重要的看一下__name__即可. 他是用来表示,你当前所在的程序是模块,还是主程序.

  • 如果你是主程序则 __name__ 为 main

  • 如果为模块则 __name__ 为 你的模块名

另外,如果你忽略参数, 直接使用dir()的话,就是用来查看当前 全局中的变量和函数名.

>>> dir()['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', '__warningregistry__', 'get', 'imp', 'sam', 'set']

但,如果你导入一个内置模块的话, 比如: copy

>>> import copy>>> dir(copy)['Error', 'PyStringMap', '_EmptyClass', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', ...]

仔细观察, 里面的内置属性, 会看到多出一个叫__all__的属性. 这其实和下面所说的包有一些关系. 实际上, __all__ 的作用, 是提供公共接口的, 但实际上, 当我们导入方法的时候, 往往会全部倒入.比如这样.

import copy

那么此时, __all__ 对于这种方法是没有任何作用, 该语句就是用来导入copy下所有的全局变量.

现在, 假设 当前模块sam.py下有2个方法,add,minus.
我将__all__ 设置为

__all__ = ['add']

我们来试验一下两者的区别:

//首先导入:>>> import sam>>> dir()['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'sam']>>> dir(sam)['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'add', 'minus']

可以看到,有了sam这个模块名. 并且, 查看sam中,会看到有add和minus方法.

然后,我们换一种方式导入:

>>> from sam import *>>> dir()['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'add']

我们会发现, minus不见了.

所以, 这里我们就可以搞懂了__all__ 到底是用来做什么的.

  • __all__: 用来设置模块的公共接口. 并且只针对于 from module import * 的语句

最后在说一下,其中的另外两个默认属性 __doc__,__file__

  • __doc__: 实际上,就是我们使用help()函数查看的内容. 内容具体就是我们写在模块开头或者函数开头的注释

  • __file__: 模块真实的文件路径, 如果你想查看源码的时候就很重要了.

放图:

python Module

Package

说完了,py中的Module, 接着就是最让你66的包. Module只是帮助我们完成了一个组件的一些小功能, 但是如果我们想要写一个可以调用的整体组件的话, 那么一个single Module显然是不够了. 所以,py 推出了package 来帮助我们完成这个巨大的工程(project). 我们可以通过个文件,调用,该组件下所有的方法. 比如,我们需要写一个html的评论框, 那么里面肯定会设计, HTML,css,js样式设计, 接收评论,发布评论等很多功能. 在包里面, 我们就可以把这些小功能进行拆分,达到复用的效果.

先看张图:
python 包
这实际上, 就是我们python包的简单格式, 在每个文件根目录都会存在__init.py__ 文件. 他的作用实际上,就是用来定义, 引用包时, 暴露的相关接口. 而关键的关键, 就是上面提到的__all__ 内置的默认关键字. how to use?
请, .
__init__.py就是一个导入文件
现在,我们来写一个简单的包, 以上图为例。
在Game的根目录下, __init__.py内容为:

__all__ = ['Sound','Image','Level']from Game import Sound,Image,Level

然后,我们就可以直接应用Game 包了.

>>>import Game>>>Game.Sound.xxx

这里,需要说明的是, 关于包的导入, 其实用不用all不是很重要, 换句话说, 应该是不推荐, 因为前文我们已经了解到, __all__ 生效的机制是 使用 from xx import * 这样的语句. 而这样做的实际效果是, 完全破坏了python的namespace机制, 也是编程语言中最重要的一个. 所以, 给的建议就是, 尽量放弃all的使用, 直接使用 import 来判断你需要导出那些公共的接口即可.

引用一段话:

Leaving an __init__.py file empty is considered normal and even a good practice, if the package’s modules and sub-packages do not need to share any code.

出自:

转载地址:http://dakwo.baihongyu.com/

你可能感兴趣的文章
惠普再“卖身”,软件业务卖给了这家鼻祖级公司
查看>>
软件定义存储的定制化怎么走?
查看>>
“上升”华为碰撞“下降”联想
查看>>
如何基于Spark进行用户画像?
查看>>
光伏发电对系统冲击大 “十三五”电力规划重点增强调峰能力
查看>>
全球19家值得关注的物联网安全初创企业
查看>>
Android下的junit 单元测试
查看>>
这几个在搞低功耗广域网的,才是物联网的黑马
查看>>
主流or消亡?2016年大数据发展将何去何从
查看>>
《大数据分析原理与实践》一一第3章 关联分析模型
查看>>
《挖掘管理价值:企业软件项目管理实战》一2.4 软件设计过程
查看>>
Capybara 2.14.1 发布,Web 应用验收测试框架
查看>>
ExcelJS —— Node 的 Excel 读写扩展模块2
查看>>
《数字短片创作(修订版)》——第一部分 剧本创作 第1章 数字短片创意技法 剧本创作的构思...
查看>>
MIT 学生挑战新泽西索取挖矿程序源代码的要求
查看>>
实践 | 不同行业WMS选型策略及需要注意的一些问题
查看>>
MaxCompute与OSS非结构化数据读写互通(及图像处理实例)
查看>>
【F3简介】一张图看懂FPGA-F3实例
查看>>
bash环境(变量与bash配置文件)
查看>>
Server Hard drive mode
查看>>