w88优德官网中文版手机_w88官方网站手机版_w88top

admin3个月前212浏览量

译文:http://codingpy.com/article/python-import-101/
原文:http://www.blog.pythonlibrary.org/2016/03/01/python-101-all-about-imports/

作为一名新手Python程序员,你首要需求学习的内容之一便是怎么导入模块或包。可是我留意到,那些许多年来不时运用Python的人并不是都知道Python的导入机制其实十分灵敏。在本文中,咱们将讨论以下论题:

  • 惯例导入(regular imports)
  • 运用from句子导入
  • 相对导入(relative imports)
  • 可选导入(optional imports)
  • 本地导入(local imports)
  • 导入留意事项

惯例导入

惯例导入应该是最常运用的导入办法,大概是这样的:

import sys

你只需求运用import一词,然后指定你期望导入的模块或包即可。经过这种办法导入的优点是能够一次性导入多个包或模块:

import os, sys, time

尽管这节省了空间,可是却违反了Python风格攻略。Python风格攻略主张将每个导入句子独自成行

有时在导入模块时,你想要重命名这个模块。这个功用很简略完结:

import sys as system
print(system.platform)

上面的代码将咱们导入的sys模块重命名为system。咱们能够依照和曾经相同的办法调用模块的办法,可是能够用一个新的模块名。也有某些子模块有必要要运用点标记法才干导入。

import urllib.error

这个状况不常见,可是对此有所了解总是没有害处的。

运用from句子导入

许多时分你只想要导入一个模块或库中的某个部分。咱们来看看在Python中怎么完结这点:

from functools import lru_cache

上面这行代码能够让你直接调用lru_cache。假如你按惯例办法导入functools,那么你就有必要像这样调用lru_cache:

functools.lru_cache(*args)

依据你实践的运用场景,上面的做法或许是更好的。在杂乱的代码库中,能够看出某个函数是从哪里导入的这点很有用的。不过,假如你的代码保护的很好,模块化程度高,那么只从某个模块中导入一部分内容也是十分便利和简练的。

当然,你还能够运用from办法导入模块的全部内容,就像这样:

from os import *

这种做法在少量状况下是挺便利的,可是这样也会打乱你的命名空间。问题在于,你或许界说了一个与导入模块中称号相同的变量或函数,这时假如你企图运用os模块中的同名变量或函数,实践运用的将是你自己界说的内容。因而,你终究或许会碰到一个适当让人困惑的逻辑过错。规范库中我仅有引荐全盘导入的模块只要Tkinter

假如你正好要写自己的模块或包,有人会主张你在__init__.py文件中导入一切内容,让模块或许包运用起来更便利。我个人更喜爱显现地导入,而非隐式地导入。

你也能够采纳折中计划,从一个包中导入多个项:

from os import path, walk, unlink
from os import uname, remove

在上述代码中,咱们从os模块中导入了5个函数。你或许留意到了,咱们是经过屡次从同一个模块中导入完结的。当然,假如你乐意的话,你也能够运用圆括号一次性导入多个项:

from os import (path, walk, unlink, uname, 
remove, rename)

这是一个有用的技巧,不过你也能够换一种办法:

from os import path, walk, unlink, uname, \
remove, rename

上面的反斜杠是Python中的续行符,通知解说器这行代码连续至下一行。

相对导入

PEP 328介绍了引进相对导入的原因,以及挑选了哪种语法。具体来说,是运用句点来决议怎么相对导入其他包或模块。这么做的原因是为了防止偶尔状况下导入规范库中的模块发作抵触。这儿咱们以PEP 328中给出的文件夹结构为例,看看相对导入是怎么作业的:

在本地磁盘上找个当地创立上述文件和文件夹。在顶层的__init__.py文件中,输入以下代码:

from . import subpackage1
from . import subpackage2

接下来进入subpackage1文件夹,修改其间的__init__.py文件,输入以下代码:

from . import module_x
from . import module_y

现在修改module_x.py文件,输入以下代码:

from .module_y import spam as ham
def main():
ham()

终究修改module_y.py文件,输入以下代码:

def spam():
print('spam ' * 3)

翻开终端,cd至my_package包地点的文件夹,但不要进入my_package。在这个文件夹下运转Python解说器。我运用的是IPython,由于它的主动补全功用十分便利:

相对导入适用于你终究要放入包中的代码。假如你编写了许多相关性强的代码,那么应该选用这种导入办法。你会发现PyPI上有许多盛行的包也是选用了相对导入。还要留意一点,假如你想要跨过多个文件层级进行导入,只需求运用多个句点即可。不过,PEP 328主张相对导入的层级不要超越两层

还要留意一点,假如你往module_x.py文件中增加了if __name__ == ‘__main__’,然后企图运转这个文件,你会碰到一个很难了解的过错。修改一下文件,试试看吧!

现在从终端进入subpackage1文件夹,履行以下指令:

python module_x.py

假如你运用的是Python 2,你应该会看到下面的过错信息:

Traceback (most recent call last):
File "module_x.py", line 1, in
from . module_y import spam as ham
ValueError: Attempted relative import in non-package

假如你运用的是Python 3,过错信息大概是这样的:

Traceback (most recent call last):
File "module_x.py", line 1, in
from . module_y import spam as ham
SystemError: Parent module '' not loaded, cannot perform relative import

这指的是,module_x.py是某个包中的一个模块,而你企图以脚本形式履行,可是这种形式不支撑相对导入

假如你想在自己的代码中运用这个模块,那么你有必要将其增加至Python的导入检索途径(import search path)。最简略的做法如下:

import sys
sys.path.append('/path/to/folder/containing/my_package')
import my_package

留意,你需求增加的是my_package的上一层文件夹途径,而不是my_package自身。原因是my_package便是咱们想要运用的包,所以假如你增加它的途径,那么将无法运用这个包。

咱们接下来谈谈可选导入。

可选导入(Optional imports)

假如你期望优先运用某个模块或包,可是一起也想在没有这个模块或包的状况下有备选,你就能够运用可选导入这种办法。这样做能够导入支撑某个软件的多种版别或许完结功用提高。以github2包中的代码为例:

正如以上示例所示,可选导入的运用很常见,是一个值得把握的技巧

部分导入

当你在部分效果域中导入模块时,你履行的便是部分导入。假如你在Python脚本文件的顶部导入一个模块,那么你便是在将该模块导入至大局效果域,这意味着之后的任何函数或办法都或许拜访该模块。例如:

这儿,咱们将sys模块导入至大局效果域,但咱们并没有运用这个模块。然后,在square_root函数中,咱们将math模块导入至该函数的部分效果域,这意味着math模块只能在square_root函数内部运用。假如咱们企图在my_pow函数中运用math,会引发NameError。试着履行这个脚本,看看会发作什么。

运用部分效果域的优点之一,是你运用的模块或许需求很长时刻才干导入,假如是这样的话,将其放在某个不常常调用的函数中或许愈加合理,而不是直接在大局效果域中导入。老实说,我简直从没有运用过部分导入,首要是由于假如模块内部处处都有导入句子,会很难分辨出这样做的原因和用处。依据约好,一切的导入句子都应该坐落模块的顶部

导入留意事项

在导入模块方面,有几个程序员常犯的过错。这儿咱们介绍两个。

  • 循环导入(circular imports)
  • 掩盖导入(Shadowed imports,暂时翻译为掩盖导入)

先来看看循环导入。

循环导入

假如你创立两个模块,二者彼此导入对方,那么就会呈现循环导入。例如:

# a.py
import b
def a_test():
print("in a_test")
b.b_test()
a_test()

然后在同个文件夹中创立另一个模块,将其命名为b.py。

import a
def b_test():
print('In test_b"')
a.a_test()
b_test()

假如你运转恣意一个模块,都会引发AttributeError。这是由于这两个模块都在企图导入对方。简略来说,模块a想要导入模块b,可是由于模块b也在企图导入模块a(这时正在履行),模块a将无法完结模块b的导入。我看过一些处理这个问题的破解办法(hack),可是一般来说,你应该做的是重构代码,防止发作这种状况

掩盖导入

当你创立的模块与规范库中的模块同名时,假如你导入这个模块,就会呈现掩盖导入。举个比如,创立一个名叫math.py的文件,在其间写入如下代码:

import math
def square_root(number):
return math.sqrt(number)
square_root(72)

现在翻开终端,试着运转这个文件,你会得到以下回溯信息(traceback):

这到底是怎么回事?其实,你运转这个文件的时分,Python解说器首要在当时运转脚本所在的的文件夹中查找名叫math的模块。在这个比如中,解说器找到了咱们正在履行的模块,企图导入它。可是咱们的模块中并没有叫sqrt的函数或特点,所以就抛出了AttributeError。

总结

在本文中,咱们讲了许多有关导入的内容,可是还有部分内容没有触及。PEP 302中介绍了导入钩子(import hooks),支撑完结一些十分酷的功用,比如说直接从github导入。Python规范库中还有一个importlib模块,值得检查学习。当然,你还能够多看看他人写的代码,不断发掘更多好用的好方法。

最新评论