Heim  >  Artikel  >  Backend-Entwicklung  >  Python-Handbuchmodul

Python-Handbuchmodul

巴扎黑
巴扎黑Original
2017-06-23 16:29:361376Durchsuche

[Übersetzung]Das Python-Tutorial#Module

6. Module

Wenn Sie den Python-Interpreter verlassen und erneut aufrufen, gehen die zuvor definierten Namen (Funktionen und Variablen) verloren. Wenn Sie längere Programme schreiben möchten, ist es daher besser, einen Texteditor zur Vorbereitung der Eingaben für den Interpreter zu verwenden und stattdessen Dateien als Eingabe zu verwenden. Dies wird auch als Erstellen eines Skripts bezeichnet. Wenn Ihr Programm länger wird, können Sie es aus Wartungsgründen möglicherweise in mehrere Dateien aufteilen. Möglicherweise möchten Sie eine nützliche Funktion auch in mehreren Programmen verwenden, ohne ihre Definition in jedes Programm zu kopieren.

Um diese Anforderungen zu unterstützen, bietet Python eine Möglichkeit, Definitionen in eine Datei zu schreiben und sie in einem Skript oder einer interaktiven Instanz des Interpreters zu verwenden. Eine solche Datei wird als Modul bezeichnet; Definitionen in einem Modul können in andere Module oder in das Hauptmodul (ein Satz von Variablen, auf die in Skripten und Berechnungsmodi der obersten Ebene zugegriffen werden kann) importiert werden. .

Ein Modul ist eine Datei, die Python-Definitionen und -Anweisungen enthält. Der Dateiname ist der Modulname und hat das Suffix .py. Innerhalb eines Moduls steht der Name des Moduls (als String) als Wert der globalen Variablen __name__ zur Verfügung. Erstellen Sie beispielsweise mit Ihrem bevorzugten Texteditor eine fibo.py-Datei im aktuellen Verzeichnis mit folgendem Inhalt:

# Fibonacci numbers moduledef fib(n):    # write Fibonacci series up to na, b = 0, 1while b < n:print(b, end=&#39; &#39;)
        a, b = b, a+bprint()def fib2(n):   # return Fibonacci series up to nresult = []
    a, b = 0, 1while b < n:
        result.append(b)
        a, b = b, a+breturn result

Geben Sie den Python-Interpreter ein und importieren Sie dieses Modul wie folgt Befehl:

>>> import fibo

Dieser Vorgang importiert nicht den Namen der in fibo definierten Funktion, sondern nur den Namen des Moduls fibo. Auf Funktionen kann über Modulnamen zugegriffen werden:

>>> fibo.fib(1000)1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]>>> fibo.__name__&#39;fibo&#39;

Wenn Sie eine Funktion häufig verwenden möchten, können Sie ihr einen lokalen Namen zuweisen:

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

6.1 Mehr zu Modulen

Module können sowohl ausführbare Anweisungen als auch Funktionsdefinitionen enthalten. Ausführbare Anweisungen werden zum Initialisieren des Moduls verwendet. Wenn der Modulname in einer Importanweisung erscheint, werden diese ausführbaren Anweisungen nur einmal ausgeführt [1]. (Wenn es sich bei der Datei um ein Skript handelt, werden diese ausführbaren Dateien ebenfalls ausgeführt)

Jedes Modul verfügt über eine eigene private Symboltabelle, die von allen im Modul definierten Funktionen als globale Symboltabelle verwendet wird. Daher können Modulautoren diese globalen Variablen verwenden, ohne sich Gedanken über versehentliche Namenskonflikte mit denen für globale Variablen machen zu müssen. Wenn Sie andererseits wissen, was Sie tun, können Sie auf die globalen Variablen eines Moduls genauso verweisen, wie Sie auf Funktionen verweisen, modname.itemname.

Module können auf andere Module verweisen. Es ist eine gute Praxis, alle import-Anweisungen am Anfang eines Moduls (oder Skripts) zu platzieren, aber es ist nicht zwingend erforderlich. Der importierte Modulname wird in die globale Symboltabelle des aktuellen Moduls eingefügt.

Es gibt eine Variante der Importanweisung, die den Modulnamen direkt in die Symboltabelle des aktuellen Moduls importiert. Zum Beispiel:

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

Oben wird der Modulname nicht eingeführt (im obigen Beispiel wird fibo nicht definiert).

Es gibt sogar eine Möglichkeit, alle in einem Modul definierten Namen zu importieren:

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

Diese Methode importiert alle Namen, die nicht mit einem Unterstrich beginnen _ . In den meisten Fällen werden Python-Programmierer diese Methode nicht verwenden, da sie einen unbekannten Satz von Namen in den Interpreter importiert und möglicherweise einige bereits definierte Namen blockiert.

Es ist zu beachten, dass in der Praxis vom Importieren aus einem Modul oder Paket in der Regel abgeraten wird, da dadurch die Lesbarkeit des Programms beeinträchtigt wird. Es ist jedoch möglich, es in einer interaktiven Umgebung zu verwenden, um die Tipparbeit zu reduzieren.

Hinweis: Aus Leistungsgründen wird jedes Modul nur einmal pro Dolmetschersitzung importiert. Daher muss bei einem Modulwechsel der Interpreter neu gestartet werden; wenn Sie ein Modul nur interaktiv testen möchten, verwenden Sie importlib.reload(), zum Beispiel: import importlib; importlin.reload(modulename)

6.1.1 Module ausführen als Skripte

Beim Ausführen eines Python-Moduls mit dem folgenden Befehl:

python fibo.py <arguments>

Der Code im Modul wird so ausgeführt, als ob das Modul importiert worden wäre, aber dann __name__ ist auf __main__ eingestellt. Das bedeutet, dass am Ende des Moduls folgender Code eingefügt wird:

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

Das Modul wird als Skript ausgeführt und kann auch als Modul importiert werden, denn nur wann Das Modul wird als mian-Datei ausgeführt. Der Code, der die Befehlszeile analysiert, wird ausgeführt:

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

Wenn das Modul importiert wird, wird der Code nicht ausgeführt:

>>> import fibo>>>

这可以用来为使用者提供一个模块用户接口的使用约定,也可以用作测试(模块作为脚本时执行测试用例)

6.1.2 The Module Search Path

当模块spam被导入时,解释器首先搜索built-in模块。如果没有找到,解释器在变量sys.path提供的路径列表中搜索名为spam.py的文件。sys.path从下列位置初始化:

  • 包含输入脚本的目录(或者没有指定文件时的当前目录)

  • PYTHONPATH(目录名字集合,与shell环境变量PATH相似,也是环境变量)

  • 安装默认目录

注意: 在支持符号链接的文件系统,包含输入脚本的目录是符号链接指向的目录。也就是说包含符号链接的目录不会被加入到搜索路径中。

初始化后,Python程序可以修改sys.path。包含执行脚本的目录被放置到搜索路径的开始,在标准库路径之前。这意味着该目录中的脚本会被加载,而标准库目录中的同名模块不会被加载。这会引发错误,除非是有意替换标准库的模块。阅读Standard Modules获取更多信息。 (译注:自定义的模块不应与标准模块重名,否则标准模块会被覆盖。)

6.1.3 “Compiled” Python files

为加速模块加载,Python会在__pycache__目录中缓存每个模块的编译版本,缓存文件名为module.version.pycversion编码了被编译文件的版本;通常包含了Python的版本号。例如,在CPython release 3.3中,文件spam.py的编译版本会被缓存为__pycache__/spam.cpython-33.pyc。这种命名约定允许来自不同Python发行版本的模块得以共存。

Python检查源文件的修改日期与编译版本,来确定编译版本是否过期,是否需要重新编译。这是一个完全自动化的过程。另外,编译模块是平台独立的,因此异构系统可以共享相同的库。

Python不会检查在两个环境中的缓存。首先,Python总是重新编译,并且不会存储直接从命令行加载的模块的结果。其次,如果没有源模块,Python不检查缓存。若要支持无源文件(只有编译版本)分布,那么编译的模块必须放在源文件目录中,并且源模块必需不存在。

给专家的建议:

  • 可以在命令行使用-O或者-OO开关来减少编译模块的大小。-O参数移除assert语句,-OO参数同时移除assert语句和__doc__字符串。由于一些程序依赖这些变量,那么只有当你确认你要这么做时,才能使用这两个参数。“优化的”模块有一个opt-标签并且通常更小。未来的发型版本可能改变优化的影响。

  • .pyc文件中读取的程序不会比从.py文件读取的程序跑得快;.pyc文件快的地方在于加载。

  • compileall模块可以为目录中的所有模块创建.pyc文件。

  • PEP 3147中有关系这点的更多信息,包括一个决策流程

6.2 Standard Modules

Python提供了标准模块库,在独立文档中描述,名为Python Library Reference(以后叫做Library Reference)。有一些模块内嵌入解释器中,这些模块不是语言核心的一部分,但是它们是内嵌的,这既是为性能考虑,也提供了访问如系统调用般的操作系统原生接口的方式。这些模块集合依赖底层平台的配置选项。例如winreg模块只在Windows系统中提供。一个特殊的模块值得注意:sys,这个模块内嵌在所有Python解释器中。变量sys.ps1sys.ps2定义了主提示符和辅助提示符的字符串:

>>> import sys>>> sys.ps1&#39;>>> &#39;>>> sys.ps2&#39;... &#39;>>> sys.ps1 = &#39;C> &#39;C> print(&#39;Yuck!&#39;)
Yuck!C>

只有当解释器以交互模式运行才会定义这两个变量。

变量sys.path是决定解释器模块搜索路径的字符列表。该变量从环境变量PYTHONPATH,或者内置默认路径(PYTHONPATH未指定时)初始化。可以使用标准list操作修改它的值:

>>> import sys>>> sys.path.append(&#39;/ufs/guido/lib/python&#39;)

6.3 The dir() Function

内嵌函数dir()用于搜索模块定义的名字。返回一个有序字符串列表:

>>> import fibo, sys>>> dir(fibo)
['__name__', 'fib', 'fib2']>>> dir(sys)  
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount', 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions']

不带参数使用dir()函数,会列出当前作用域的全部名字:

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

需要注意该函数列出所有类型的名字:变量,模块,函数,等等。

dir()不会列出内嵌函数和变量的名字。如果希望列出,这些名字定义在标准模块builtins中:

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

6.4 Packages

包是使用“圆点模块名”结构化Python模块名字空间的方式。例如,模块名A.B表示包A中的子模块B。就像模块使得不同模块的作者免于担忧每个模块的全局名字一样,圆点模块名的使用使得多模块包(如NumPy或者Python图像库)的作者免于担忧每个模块的名字。

假设需要为统一音频文件和音频数据的处理设计一个模块的集合(包)。有许多不同的音频文件格式(通常通过扩展名辨认,如.wav, .aiff, .au),因此需要为不同文件格式的转换创建和维护一个持续增长的模块集合。也存在许多对音频数据不同的操作(例如混合,增加回声,增加均衡器函数,创建人造立体效果),因此需要额外编写执行这些操作的大量模块。以下是包的可能结构(以层级文件结构来表示):

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

导入包时,Python搜索sys.path提供的路径寻找包子目录。

为使Python将普通目录看做包,目录中必须包含__init__.py文件。这样做是为了避免普通的目录名(如string)将以后会出现在模块搜索路径中的有效模块无意识的隐藏掉。最简单的情况是,__init__.py可以是一个空文件,但是它也可以包含可执行的初始化包的代码或者设置__all__变量,后面讲述。

包的用户可以从包中导入独立的模块:

import sound.effects.echo

这将加在子模块sound.effects.echo。必须使用全名引用:

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

导入子模块可选方式:

from sound.effects import echo

以上也加载子模块echo,不使用包前缀引用模块,因此可以像下面一样使用:

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

另外的方式是直接导入需要的函数或者变量:

from sound.effects.echo import echofilter

同样的,这将加在子模块echo,但使函数echofilter()直接可用:

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

注意当使用from package import item时,item可以使子模块(子包),也可以是包内定义的其他名字,如函数,类或者变量。import语句首先测试要导入的项是否在包中存在;如果不存在,Python假设这个项是模块并尝试加载它。如果最后寻找失败,ImportError异常抛出。

相对的,使用import item.subitem.subsubitem时,除了最后一项,每一项都必须是包;最后一项可以是模块或者包但是不能是前面的项中定义的类,函数或者变量。

6.4.1 Importing * From a Package

使用from sound.effects import *会发生什么?理想情况下,总是期望在文件系统中找出所有子模块,并全部导入。全部导入会耗费很长时间,并且导入子模块可能会有不期待的副作用,这些副作用应该在显式导入时发生。

唯一的解决方案是包作者提供一个包的显式索引。import语句遵循以下约定:如果包的__init__.py代码中定义了名为__all__的变量,那么使用from package import *时会导入该变量指定的所有模块。当包的新版本发布时,由包作者负责更新列表__all__。如果包作者不希望可以使用from package import *导入包中的模块,也可以不支持__all__。 例如,文件sound/effects/__init__.py可能包含以下代码:

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

这意味着from sound.effects import *会导入sound包中指定的三个模块。

如果__all__没有定义,语句from sound.effects import *不会将包sound.effects中的子模块全部倒入到当前名字空间中,只保证包sound.effects被导入了(可能会运行__init__.py中的初始化代码)并且导入任意在包中定义的名字。包括在__init__.py中定义的任意名字(以及显式加载的子模块)。也会包括前面的import语句显式加载的任意包子模块。考虑如下代码:

import sound.effects.echoimport sound.effects.surroundfrom sound.effects import *

这个例子中,echosurround模块被导入到当前名字空间中,因为执行from... import时,它们已经定义在sound.effects包中定义了。(定义了__all__时同样有效)

尽管使用import *时只有符合特定模式的名字会被导出,但仍然不建议在生产代码中使用。

记住,使用form Package import specific_submodle没有错误。实际上,这是推荐的方法,除非当前模块需要使用其他包中的同名模块。

6.4.2 Intra-package References

当包中包含了子包结构(就如例子中的sound包),可以使用绝对导入的方式引用兄弟包中的子模块。例如,如果模块sound.filters.vocoder需要使用包sound.effects中的echo模块,可以使用from sound.effects import echo

也可以使用from modul import name语句来相对导入模块。这种方式使用点.指示当前包和相对导入中涉及的父包。以surround模块为例:

from . import echofrom .. import formatsfrom ..filters import equalizer

相对导入基于当前模块的名字。由于主模块的名字总是__main__,要当做Python应用主模块使用的模块必须总是使用绝对导入的方式。

6.4.3 Packages in Multiple Directories

包还支持一个特殊属性,__path__。在__init__.py中的代码执行之前,属性__path__被初始化为一个列表,这个列表包含了持有该__init__.py文件的目录的路径。该变量可修改,这样做会影响将来的对包内模块和子包的搜索。

然而这个特性不总是需要的,它可以用来扩展包的模块集合

Footnotes

[1] 实际上,函数定义也是可“执行”的“语句”;模块级别的函数执行将函数的名字放置到模块的全局符号表中

Das obige ist der detaillierte Inhalt vonPython-Handbuchmodul. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:KlassenansichtNächster Artikel:Klassenansicht