The Python Tutorial - C6 Modules

1 深入模块

1 模块定义,执行module,pyc
2 标准模块库:module search path
3 dir()函数:__builtins__
4 包:导入模块,导入包,导入*,子包参考,__path__

1.0

每个module都有一个name
建议(google style guide import只用于package或者module):

但是it is okay to use it to save typing in interactive sessions.
import fibo
>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'

from fibo import fib, fib2
from fibo import * 这样可以导入所有除了以下划线( _ )开头的命名,但是不建议这样做,会覆盖原来重名的内容

1.1 Executing modules as scripts

A module can contain executable statements as well as function definitions. These statements are intended to initialize the module. They are executed only the first time the module name is encountered in an import statement. 1 (They are also run if the file is executed as a script.)

简单来说,每次import只有首次会执行

When you run a Python module with
python fibo.py <arguments>
the code in the module will be executed, just as if you imported it, but with the __name__ set to "__main__". That means that by adding this code at the end of your module:

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

简单来说,就是脚本运行module时,__name__就变成了__main__

you can make the file usable as a script as well as an importable module, because the code that parses the command line only runs if the module is executed as the “main” file:

1.2 The Module Search Path

当spam被import的时候,先搜索built-in module with that name,然后搜索sys.path(由当前目录,PYTHONPATH,the installation-dependent default 组成)
初始化过后,可以修改sys.path。Python程序可以更改 sys.path。包含正在运行脚本的文件目录被放在搜索路径的开头处, 在标准库路径之前。这意味着将加载此目录里的脚本,而不是标准库中的同名模块。 除非有意更换,否则这是错误。更多信息请参阅 标准模块
python搜索路径
https://blog.csdn.net/liang19890820/article/details/76219560
文件目录
https://github.com/onlytiancai/codesnip/blob/master/mypost/How_to_write_high-quality_python_program.md

1.3 编译过的python文件

为了加速模块载入,会在pycache目录缓存module.version.pyc编译版本,两种情况不检查缓存:从命令行直接载入的模块,直接重新编译并且不存储编译结果;其次,没有源模块,也不会检查缓存。
小建议:用-o 和-oo减少编译后模块的大小;compileall模块可以为一个目录下的所有模块创建.pyc文件。

2 标准模块库

有些模块库是内置于解释器里面的(用c来写的)
怎么判断内置模块
https://codeday.me/bug/20190619/1238085.html
python内置模块和标准库
https://www.cnblogs.com/pluse/p/8667864.html
sys.path 是解释器模块搜索路径的字符串列表。它由环境变量 PYTHONPATH 初始化
import sys
sys.path.append('/ufs/guido/lib/python')
运行脚本的当前目录放在最前面,即''

['', '/anaconda3/lib/python36.zip', '/anaconda3/lib/python3.6', '/anaconda3/lib/python3.6/lib-dynload', '/Users/zhanggaochao/.local/lib/python3.6/site-packages', '/anaconda3/lib/python3.6/site-packages', '/anaconda3/lib/python3.6/site-packages/aeosa', '/anaconda3/lib/python3.6/site-packages/thrift-0.11.0-py3.6-macosx-10.7-x86_64.egg', '/anaconda3/lib/python3.6/site-packages/wget-3.2-py3.6.egg']

3 dir()函数

用于按模块名搜索模块定义,它返回一个字符串类型的存储列表:

>>> dir(fibo)
['__name__', 'fib', 'fib2']

无参数调用时,dir() 函数返回当前定义的名称:

>>> dir()
['__builtins__', '__doc__', '__file__', '__name__', 'a', 'fib', 'fibo', 'sys']

注意:它列出所有类型的名称:变量,模块,函数,等等。
dir() 不会列出内置函数和变量名。如果你想列出这些内容,它们在标准模块 builtins 中定义:

>>> import builtins
>>> dir(builtins)

4 包

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py

The __init__.py files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, such as string, unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.
为什么必须要有__init__.py
https://stackoverflow.com/questions/14147990/why-does-python-require-init-py-to-treat-directories-as-containing-packages
简单来说,就是你当前目录有一个跟标准库同名的目录,你不想导入这个,但是如果没有__init__.py的话,你导入的总是这个(当前目录在sys.path最前面)
3种方式调用

  • 直接导入单个模块
    import sound.effects.echo;sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

  • 导入子模块的另一种方法
    from sound.effects import echo;echo.echofilter(input, output, delay=0.7, atten=4)

  • 直接导入所需要的函数或变量
    from sound.effects.echo import echofilter

使用 from package import item 方式导入包时,这个子项(item)既可以是包中的一个子模块(或一个子包),也可以是包中定义的其它命名,像函数、类或变量

使用类似 import item.subitem.subsubitem 这样的语法时,这些子项必须是包,最后的子项可以是包或模块,但不能是前面子项中定义的类、函数或变量。

4.1 从包中导入*

设置__all__命令导入固定包,这时就会把注册在__init__.py文件中__all__列表中的模块和包导入到当前文件中来。

For example, the file sound/effects/__init__.py could contain the following code:
__all__ = ["echo", "surround", "reverse"]

This would mean that from sound.effects import * would import the three named submodules of the sound package.
https://www.cnblogs.com/Lands-ljk/p/5880483.html

可以被import语句导入的对象是以下类型:

模块文件(.py文件)
C或C++扩展(已编译为共享库或DLL文件)
包(包含多个模块)
内建模块(使用C编写并已链接到Python解释器中)
当导入模块时,解释器按照sys.path列表中的目录顺序来查找导入文件。

导入模块

模块通常为单独的.py文件,可以用import直接引用,可以作为模块的文件类型有.py、.pyo、.pyc、.pyd、.so、.dll

在导入模块时,解释器做以下工作:

  • 已导入模块的名称创建新的命名空间,通过该命名空间就可以访问导入模块的属性和方法。

  • 在新创建的命名空间中执行源代码文件。

  • 创建一个名为源代码文件的对象,该对象引用模块的名字空间,这样就可以通过这个对象访问模块中的函数及变量

import 语句可以在程序的任何位置使用,你可以在程序中多次导入同一个模块,但模块中的代码仅仅在该模块被首次导入时执行。后面的import语句只是简单的创建一个到模块名字空间的引用而已。

sys.modules字典中保存着所有被导入模块的模块名到模块对象的映射。

导入包

__init__.py
每次导入一个包,其实是导入了__init__.py文件,可以在__init__.py里面导入,就不用一个一个导入了。

如果没有定义 __all__from sound.effects import * 语句 会从包 sound.effects 中导入所有子模块到当前命名空间;它只确保导入了包 sound.effects (可能运行任何在 __init__.py 中的初始化代码),然后导入包中定义的任何名称。这包括 __init__.py定义的任何名称(以及显式加载的子模块)。它还包括由之前的 import 语句显式加载的包的任何子模块。

请记住,使用 from package import specific_submodule 没有任何问题! 实际上,除非导入的模块需要使用来自不同包的同名子模块,否则这是推荐的表示法。

# package
# __init__.py
import re
import urllib
import sys
import os

# a.py
import package 
print(package.re, package.urllib, package.sys, package.os)

多个相关联的模块组成一个包,以便于维护和使用,同时能有限的避免命名空间的冲突。一般来说,包的结构可以是这样的:

package
  |- subpackage1
      |- __init__.py
      |- a.py
  |- subpackage2
      |- __init__.py
      |- b.py

有以下几种导入方式:

import subpackage1.a # 将模块subpackage.a导入全局命名空间,例如访问a中属性时用subpackage1.a.attr
from subpackage1 import a # 将模块a导入全局命名空间,例如访问a中属性时用a.attr_a
from subpackage.a import attr_a # 将模块a的属性直接导入到命名空间中,例如访问a中属性时直接用attr_a

使用from语句可以把模块直接导入当前命名空间,from语句并不引用导入对象的命名空间,而是将被导入对象直接引入当前命名空间。

4.2 子包参考

当包被构造成子包时(与示例中的 sound 包一样),你可以使用绝对导入来引用兄弟包的子模块。例如,如果模块 sound.filters.vocoder 需要在 sound.effects 包中使用 echo 模块,它可以使用 from sound.effects import echo 。
请注意,相对导入是基于当前模块的名称进行导入的。由于主模块的名称总是 "main" ,因此用作Python应用程序主模块的模块必须始终使用绝对导入。

from . import echo
from .. import formats
from ..filters import equalizer

4.3 多个目录中的包

包支持另一个特殊属性, __path__ 。它被初始化为一个列表,其中包含在执行该文件中的代码之前保存包的文件 __init__.py 的目录的名称。这个变量可以修改;这样做会影响将来对包中包含的模块和子包的搜索。
虽然通常不需要此功能,但它可用于扩展程序包中的模块集。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容