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

畅快了. 写了这么久的js, 连内部的模块的包都搞的这么复杂... 艹...
在python中, 已经定义好了完美的模块和包的引用机制.
我们先来看看Module

Module

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

// 命令为sam.py
def 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 sys
sys.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 sb
sb.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+b
print(add(1,2))
//接着,我多次引用
>>> import sam
3
>>> import sam

只会出现一次, 说明, sam Module 只能导入一次. 其余的就 nonesense. 但是,如果你的模块是内部循环型的, 那这样不就go die了吗?
hehe ~ py 早教看到这一点了, 在内置的imp中提供了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__: 模块真实的文件路径, 如果你想查看源码的时候就很重要了.

放图:

Package

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

这实际上, 就是我们python包的简单格式, 在每个文件根目录都会存在__init.py__ 文件. 他的作用实际上,就是用来定义, 引用包时, 暴露的相关接口. 而关键的关键, 就是上面提到的__all__ 内置的默认关键字. how to use?
请, stackoverflow.
__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.

出自: python guider

Python 中的模块和包相关推荐

  1. python哪里下载import包-详解python中的模块及包导入

    python中的导入关键字:import 以及from import 1.import import一般用于导入包以及模块. 不过有个小问题: (1)当导入的是模块的时候是可以直接可以使用模块内的函数 ...

  2. python中的模块和包

    模块 一 什么是模块 模块就是一组功能的集合体,可以通过导入模块来复用模块的功能. 比如我在同一个文件夹定义两个.py文件,分别命名为A.py和B.py,那么可以通过在A文件里通过import B来使 ...

  3. Python中的模块和包:模块的(动态)导入、__future__模块使用

    包的作用 不同的开发人员写了相同名字的模块,可以将同名的模块放入不同的包中进行管理.引用一个完整的模块代码如下: import sqz.util 在文件系统当中,包就是一个文件夹,而模块是一个.py文 ...

  4. python中导入模块或包语句_Python中导入模块或包语句

    这篇文章作者主要讨论了Python的from import *和from import *,它们怎么执行以及为什么使用这种语法(也许)是一个坏主意. 从一个模块导入全部 from import * m ...

  5. python中sys模块有问题_python中sys模块之输入输出错误流

    import sys sys.stdout.write("msg")   # 控制台白色字体打印 普通输出流 sys.stderr.write("msg") # ...

  6. Python基础之模块和包

    Python基础之模块和包 本节将介绍Python中的模块和包的概念及基本用法. 模块 简单来说模块就是一个python文件,我们可以将一些常量.函数.类等封装到一个模块中,然后在程序中使用该模块.模 ...

  7. python之路——模块和包

    一.模块 1.什么是模块? 常见的场景:一个模块就是一个包含了Python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1.使用Python编 ...

  8. python sys模块作用_浅谈Python中的模块

    模块 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在Python中,一个.py文件就称之为一个模块(Mod ...

  9. python中importlib模块安装_Python中标准模块importlib详解

    Python中标准模块importlib详解 模块简介 Python提供了importlib包作为标准库的一部分.目的就是提供Python中import语句的实现(以及__import__函数).另外 ...

最新文章

  1. pandas dataframe中的列进行重新排序、倒排、正排、自定义排序详解及实践
  2. centos7 搭建nfs共享文件
  3. scrapy第一发——基础巩固
  4. 基于RBAC的权限设计模型
  5. ps怎么清屏_黑洞PS大赛刷屏!最后一张扎心了……
  6. 前端开发者必备的代码开源平台
  7. perl - Java调用perl
  8. sd卡、U盘作为启动盘后容量变小处理方法
  9. 计算机工作日志如何调取,怎样查找电脑日志?
  10. 数学建模PPT(二)
  11. ESP8266-WIFI模块使用AT指令连接外网服务器
  12. 《超越感觉:批判性思考指南》读书笔记
  13. ipad无法更新最新版本ipadOS 16、不再连接到互联网解决方法
  14. 【Oracle】082基础知识
  15. 微信公众平台开发实例(琴岛学院校园之声) PHP开发 代码挂载SAE平台(五)琴院Siri功能
  16. 登录逻辑漏洞整理集合
  17. scrapy爬取——阿里招聘信息
  18. 如何用代理解决api接口跨域问题
  19. Zookeeper-开源客户端 之 Curator
  20. 致程序员:过了一面二面,千万别栽在HR面——70道HR面试题分享

热门文章

  1. JUnit 3一个例子就懂
  2. 活动目录域结构和域信任关系建立实验
  3. Web开发融会贯通: 深入浅出 告别浮云
  4. DHTML之-----document.selection 的 createRange
  5. jq设置checked是否选中_javascript之jquery如何判断input type=checkbox中checked是否存在选中项呢?...
  6. 酒店管理系统c语言带注释,酒店管理系统--C语言版.pdf
  7. 发送消息时,设定TTL
  8. RabbitMQ fanout交换机(消费者)
  9. 手写自己的MyBatis框架-操作流程
  10. MVC 顶层设计-ModelAndView