乐趣区

关于python:那些Python中的模块

简介
Python 的解释环境是很好用,然而如果咱们须要编写一个大型的程序的时候,解释环境就齐全不够用了。这个时候咱们须要将 python 程序保留在一个文件里。通常这个文件是以.py 结尾的。
对于大型的应用程序来说,一个文件可能是不够的,这个时候咱们须要在文件中援用其余的文件,这样文件就叫做模块。
模块是一个蕴含 Python 定义和语句的文件。文件名就是模块名后跟文件后缀 .py。在模块外部,模块名能够通过全局变量 name 取得。
模块根底
还是之前的斐波拉赫数列的例子,咱们在 fibo.py 文件中寄存了函数的实现:

def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

编写结束之后,咱们能够在 Python 的解释环境中导入它:

>>> import fibo

而后间接应用即可:

>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

罕用的函数,咱们能够将其赋值给一个变量:

>>> fib = fibo.fib
>>> fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

或者,咱们在导入的时候,间接给这个模块起个名字:

>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

或者导入模块中的函数:

>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

每个模块都有它本人的公有符号表,该表用作模块中定义的所有函数的全局符号表。因而,模块的作者能够在模块内应用全局变量,而不用放心与用户的全局变量发生意外抵触。
执行模块
后面咱们提到了能够应用 import 来导入一个模块,并且 name 中保留的是模块的名字。
和 java 中的 main 办法一样,如果咱们想要在模块中进行一些测试工作,有没有相似 java 中 main 办法的写法呢?
先看一个例子:

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

在模块中,咱们须要进行一个判断 name 是不是被赋值为 “__main__”。
咱们这样来执行这个模块:

python fibo.py <arguments>

以脚本执行的状况下,模块的 name 属性会被赋值为 main , 这也是例子中为什么要这样写的起因。
看下执行成果:

$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34

如果是以模块导入的话,那么将不会被执行:

>>> import fibo
>>>

模块搜寻门路
应用 import 导入模块的时候,解释器首先会去找该名字的内置模块,如果没找到的话,解释器会从 sys.path 变量给出的目录列表里寻找。
sys.path 的初始目录包含:

当前目录
PYTHONPATH 指定的目录
装置的默认值

dir
要想查看模块中定义的内容,能够应用 dir 函数。

>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']

下面的例子列出了以后模块中定义的内容,包含变量,模块,函数等。

留神,dir() 不会列出内置函数和变量的名称。如果你想要这些,它们的定义是在规范模块 builtins 中。

咱们能够给 dir 加上参数,来获取特定模块的内容:

>>> import builtins
>>> dir(builtins)  
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
 'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
 'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError',
 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
 '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
 'zip']


java 中有 package 的概念,用来隔离程序代码。同样的在 Python 中也有包。
咱们看一个 Python 中包的例子:

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
              ...

下面咱们定义了 4 个包,别离是 sound,sound.formats, sound.effects, sound.filters。

留神,如果是包的话,外面肯定要蕴含 __init__.py 文件。

init__.py 能够是一个空文件,也能够执行包的初始化代码或设置 __all 变量。
当导入的时候,python 就会在 sys.path 门路中搜寻该包。
包的导入有很多种形式,咱们能够导入单个模块:

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

而后这样应用:

echofilter(input, output, delay=0.7, atten=4)

如果一个包外面的子包比拟多,咱们可能会心愿应用 * 来一次性导入:

 from sound.effects import * 

那么如何去管制到底会导入 effects 的哪一个子包呢?
咱们能够在 init__.py 中定义一个名叫 __all 的列表,在这个列表中列出将要导出的子包名,如下所示:

__all__ = ["echo", "surround", "reverse"]

这样 from sound.effects import * 将导入 sound 包的三个命名子模块。
如果没有定义 __all__,from sound.effects import * 语句 不会 从包 sound.effects 中导入所有子模块到以后命名空间;它只会导入包 sound.effects。
包的相对路径
Import 能够指定相对路径,咱们应用 . 来示意以后包,应用 .. 来示意父包。
如下所示:

from . import echo
from .. import formats
from ..filters import equalizer
退出移动版