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
的目录的名称。这个变量可以修改;这样做会影响将来对包中包含的模块和子包的搜索。
虽然通常不需要此功能,但它可用于扩展程序包中的模块集。