当前位置: 首页 > 编程笔记 >

Python中使用语句导入模块或包的机制研究

王岳
2023-03-14
本文向大家介绍Python中使用语句导入模块或包的机制研究,包括了Python中使用语句导入模块或包的机制研究的使用技巧和注意事项,需要的朋友参考一下

这篇文章讨论了Python的from <module> import *和from <package> import *,它们怎么执行以及为什么使用这种语法(也许)是一个坏主意。
从一个模块导入全部

from <module> import * means意味着“我希望能访问<module>中我有权限访问的全部名称”。例如以下代码something.py:
 

# something.py
 
public_variable = 42
_private_variable = 141
 
def public_function():
  print("I'm a public function! yay!")
 
def _private_function():
  print("Ain't nobody accessing me from another module...usually")
 
class PublicClass(object):
  pass
 
class _WeirdClass(object):
  pass

在Python解释器中,我们可以执行from something import *,然后看到如下的内容:
 

>>> from something import *
>>> public_variable
42
>>> _private_variable
...
NameError: name '_private_variable' is not defined
>>> public_function()
"I'm a public function! yay!"
>>> _private_function()
...
NameError: name '_private_function' is not defined
>>> c = PublicClass()
>>> c
<something.PublicClass object at ...>
>>> c = _WeirdClass()
...
NameError: name '_WeirdClass' is not defined

from something import *从something中导入了除了以_开头名称外的其他所有名称,按照规范,_开始的名称是私有的所以未被导入。
嗯,不是特别糟!还有什么?

上面没提到__all__是什么。__all__是一个字符串列表,指定了当from <module> import *被使用时,模块(或者如后文会提到的包)中的哪些符号会被导出。如果我们不定义__all__(我们在上面的something.py就没定义),import *默认的导入方式是导入除了下划线(_)开头的所有名称。再说一次,编程惯例上下划线表示一个符号是私有的,不导入是合理的。让我们来看看在something.py中定义我们自己的__all__会发生什么。
 

# something.py
 
__all__ = ['_private_variable', 'PublicClass']
 
# The rest is the same as before
 
public_variable = 42
_private_variable = 141
 
def public_function():
  print("I'm a public function! yay!")
 
def _private_function():
  print("Ain't nobody accessing me from another module...usually")
 
class PublicClass(object):
  pass
 
class _WeirdClass(object):
  pass

现在,我们期望from something import *只会导入_private_variable和PublicClass:
 

>>> from something import *
>>> public_variable
42
>>> _private_variable
...
NameError: name '_private_variable' is not defined
>>> public_function()
"I'm a public function! yay!"
>>> _private_function()
...
NameError: name '_private_function' is not defined
>>> c = PublicClass()
>>> c
<something.PublicClass object at ...>
>>> c = _WeirdClass()
...
NameError: name '_WeirdClass' is not defined

包是怎样的呢?

当从一个包中导入全部时,__all__的做法和模块基本一样,不过它处理的是包中的模块(而不是把模块中的名都导入)。所以当我们使用from <package> import *.时__all__说明了所有需要被导入当前命名空间的模块。

不同之处在于,如果你在一个包的__init__.py里面没有声明__all__,from <package> import *语句不会导入任何东西(这个说法也不全对,正确的说法在此)
但是,这有什么不好?

继续读之前,在你的Python解释器中,执行import this,再读一遍Python之禅(在你孩子每晚睡前也要读给他们)。

    明确比含糊要好。

from <module> import * 是不明确的。它没告诉我们我们正在导入什么或者我们把什么带入当前命名空间了。更好的做法是显式地导入我们需要的全部名称。这种方式下,读者(非常可能是未来的你自己)就不会困惑于你代码中使用的一个变量/方法/类/其他东西是哪儿来的,这也告诉了我们下一点:

    可读性很重要

即使你需要导入很多东西,一个一个显式地导入也更清楚。使用PEP 328:
 

from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
  LEFT, DISABLED, NORMAL, RIDGE, END)

你现在就能明确知道你的命名空间里有什么,使用ctrl+f能很快地告诉你它们是哪儿来的。

同时,你还总是要承担模块/包作者更改list内容(加/减东西)的风险。也就是下面两者之一:

    作者从__all__里删除了一个字符串。如果你的代码使用了那个名字,你的代码就会报出NameError的错误,并且很难发现为什么。
    作者在__all__里加入了很多东西。你也许不需要这些增加的内容,所以你只是让这些你不关心的东西占满了你的命名空间。他们甚至在你不注意的时候会替代其他同名内容。

当然,有时候从模块或者包中导入全部内容是有用的。不过,这么做之前三思。从我的经验来看,这么做通常只是因为懒。

 类似资料:
  • 问题内容: 已经使用了平面软件包,我没想到嵌套软件包会遇到这个问题。这是… init .py的内容 这两个和是空的。 内容 内容(3个版本) 版本1 这是导入事物的坏方法和不安全方法(批量导入所有内容),但是它可以工作。 版本2 一种逐项导入的更安全的方法,但是失败了,Python不希望这样:失败,并显示消息:“没有名为模块的模块”。但是…… ……说。所以这是一个模块,但不是一个模块/ -P 8-

  • 问题内容: 我已尝试找到有关最佳使用还是全面的指南。我刚开始使用Python,并且正在尝试着眼于最佳实践。 基本上,我希望有人能分享他们的经验,其他开发人员有什么喜好,以及避免遇到麻烦的最佳方法是什么? 问题答案: 和之间的区别主要是主观的。选择最喜欢的一个,并在使用中保持一致。这里有一些要点可以帮助你做出决定。 优点: - 减少维护你的import报表。无需添加任何其他导入即可开始使用模块中的另

  • 当我尝试导入诸如“pymc3”或“theano”之类的模块时,rPython或pythoniner无法定位这些模块,即使我已经安装了它们。我使用的是Ubuntu 16.04、R3.4.2和python 3.5.2 这两个包似乎无法找到某个文件夹,但是在我将路径追加到sys.path后,它就不起作用了,sys.path包含了我需要的所有包,通过使用以下命令: 结果似乎也不错: ['''/usr/li

  • 本文向大家介绍Python 中的 import 机制之实现远程导入模块,包括了Python 中的 import 机制之实现远程导入模块的使用技巧和注意事项,需要的朋友参考一下 所谓的模块导入( import ),是指在一个模块中使用另一个模块的代码的操作,它有利于代码的复用。 在 Python 中使用 import 关键字来实现这个操作,但不是唯一的方法,还有 importlib.import_m

  • 我有一本书。节点js(07.10.19版本的node.js的最新版本)应用程序中的ts文件,带有导入节点模块而无默认导出。我使用这种结构:

  • 我有一个ApolloServer项目给我带来了麻烦,所以我想我可能会更新它,并在使用最新的巴别塔时遇到问题。我的“index.js”是: 当我运行它时,我得到了错误 首先,我试图做一些事情来说服TPTB*这是一个模块(没有成功)。所以我把“导入”改成了“要求”,这就奏效了。 但是现在我在其他文件中有大约24个“导入”给我同样的错误。 *我确信我的问题的根源是我甚至不确定是什么在抱怨这个问题。我有点