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__里加入了很多东西。你也许不需要这些增加的内容,所以你只是让这些你不关心的东西占满了你的命名空间。他们甚至在你不注意的时候会替代其他同名内容。

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

(0)

相关推荐

  • Python中的模块导入和读取键盘输入的方法

    导入模块 import 语句 想使用Python源文件,只需在另一个源文件里执行import语句,语法如下: import module1[, module2[,... moduleN] 当解释器遇到import语句,如果模块在当前的搜索路径就会被导入. 搜索路径是一个解释器会先进行搜索的所有目录的列表.如想要导入模块hello.py,需要把命令放在脚本的顶端: #!/usr/bin/python # -*- coding: UTF-8 -*- # 导入模块 import support # 现

  • 从零学python系列之新版本导入httplib模块报ImportError解决方案

    之前用Python 2.7版本的httplib做接口测试时,运行代码都是正常的, 最近开始用Python 3.3之后,再去看以前的代码,发现import httplib出现错误:Unresolved import :httplib, 运行代码时也报错:ImportError: No module named 'httplib' 查找各种资料发现原来Python 2.x中的"httplib"模块在Python 3.x中变成了"http.client",就怪之前只了解了

  • Python创建模块及模块导入的方法

    本文实例讲述了Python创建模块及模块导入的方法.分享给大家供大家参考.具体分析如下: python学习手册中写道: 定义模块,只要使用文本编辑器,把一些python代码输入到文本中,然后以.py为后缀名进行保存,任何此类文件都会被认为是python模块. 比如说,下面的代码输入到一个文件中,就可以看作是一个模块: def printme(var): print var if __name__ == '__main__': printme(1) 假设说输入到a.py中,那么import a就可

  • Python导入模块时遇到的错误分析

    当遇到无法导入某个python模块时,可能会是没有安装某个模块,也有可能是某模块在加载过程中失败,也有可能是陷入了循环导入的问题.本文详细解释了这个问题. 1. 模块未安装或者路径不对 ImportError: No mudule named myModule 有两种可能,一是该模块没有安装,一般可以用 pip install %module_name% 来解决.注意有时候模块安装包名并不等于要导入的模块名.这种情况下可以通过pip search | list命令来尝试找到正确的包. 另一种情况

  • python根据路径导入模块的方法

    本文实例讲述了python根据路径导入模块的方法,分享给大家供大家参考.具体方法如下: 常规做法如下: import sys sys.path.append('C:/full/path') from foo import util,bar 而要直接通过路径 import imp util = imp.load_source('util', 'C:/full/path/foo/util.py') 使用时使用util.method,此时并没有定义method method = util.method

  • Python中import导入上一级目录模块及循环import问题的解决

    import上一级目录的模块 python中,import module会去sys.path搜索,sys.path是个列表,并且我们可以动态修改. 要import某个目录的module,我们sys.path.insert(0,somedir)来加入搜索路径,就可以import了. 既然这样,要import上一级目录的module,可以sys.path.insert(0,parentdir). 不过这种写绝对路径的方式,如果文件放到其它地方,就不行了. 所以用动态方法来获取上一级目录. impor

  • Python使用xlrd模块操作Excel数据导入的方法

    本文实例讲述了Python使用xlrd模块操作Excel数据导入的方法.分享给大家供大家参考.具体分析如下: xlrd是一个基于python的可以读取excel文件的产品.和pyExcelerator相比,xlrd的主要特点在于读的功能比较强大,提供了表单行数.列数.单元格数据类型等pyExcelrator无法提供的详细信息,使得开发人员无须了解表单的具体结构也能对表单中的数据进行正确的分析转换. 但是xlrd仅仅提供了读取excel文件的功能,不能像pyExcelrator那样生成excel文

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

    这篇文章讨论了Python的from <module> import *和from <package> import *,它们怎么执行以及为什么使用这种语法(也许)是一个坏主意. 从一个模块导入全部 from <module> import * means意味着"我希望能访问<module>中我有权限访问的全部名称".例如以下代码something.py: # something.py public_variable = 42 _priv

  • Python中几种导入模块的方式总结

    模块内部封装了很多实用的功能,有时在模块外部调用就需要将其导入.常见的方式有如下几种: 1 . import >>> import sys >>> sys.path ['', 'C:\\Python34\\Lib\\idlelib', 'C:\\Windows\\system32\\python34.zip', 'C:\\Python34\\DLLs', 'C:\\Python34\\lib', 'C:\\Python34', 'C:\\Python34\\lib\\s

  • 简单谈谈python中的语句和语法

    python程序结构 python"一切皆对象",这是接触python听到最多的总结了.在python中最基层的单位应该就是对象了,对象需要靠表达式建立处理,而表达式往往存在于语句中,多条语句组成代码块,多个代码块再组成一整个程序.python的核心其实是由语句和表达式组成.所以在这里简单探讨一下python中的语句和表达式. 因为以后可能会接触到两个版本的python,所以这里讲一讲python2与python3的语句差异: 1.python2中没有nolocal语句. 2.prin

  • Python中如何引入第三方模块

    Python中怎么使用第三方模块? 在Python可以在代码中导入模块,然后就可以使用第三方模块了. import 语句 想使用Python源文件,只需在另一个源文件里执行import语句,语法如下: import module1[, module2[,... moduleN] 当解释器遇到import语句,如果模块在当前的搜索路径就会被导入. 搜索路径是一个解释器会先进行搜索的所有目录的列表.如想要导入模块hello.py,需要把命令放在脚本的顶端: #!/usr/bin/python # -

  • Python中常见的导入方式总结

    一.直接导入模块 import 模块名 优点:干净直接 import sys print(sys.path) import os # os是一个模块 import os.path # 注意这里的os.path是一个模块 二.直接导入包 import 包名 如果只导入包,在调用时不可使用.来找到模块,但可以访问到__init__.py下的类和函数. import bs4 # 注意这里bs4是一个包! soup = bs4.BeautifulSoup(...) # 可以访问到包中__init__.p

  • Python中的pandas表格模块、文件模块和数据库模块

    目录 一.Series数据结构 1.Series的创建 2.Series属性 2.Series缺失数据处理 二.DataFrame数据结构 1.DataFrame的创建 2.DataFrame属性 3.DataFrame取值 4.DataFrame值替换 5.处理丢失数据 6.合并数据 二.读取CSV文件 三.导入导出数据 1.读取文件导入数据 2.写入文件导出数据 3.实例 四.pandas读取json文件 五.pandas读取sql语句 pandas官方文档:https://pandas.p

  • 浅析Python中else语句块的使用技巧

    学过C/C++的都知道,else语句是和if语句搭配使用的,但是在Python中,else语句更像是作为一个模块,不仅仅可以和if语句搭配,还可以和循环语句,异常处理语句搭配使用. 下面逐个进行介绍: <1> if 语句 条件表达式为真的时候,执行代码块1,否则执行代码块2. (其实就是一个二选一的问题,必然有一个执行) Python中if...else...的扩展模式:多个if条件判断,如下图所示:整个代码块的执行,是顺着某些箭头方向走到结束(图中的黑点). 这里需要注意的是,表达式1,2,

  • python中os和sys模块的区别与常用方法总结

    前言 本文主要介绍了关于python中os和sys模块区别与常用方法的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 官方解释: os: This module provides a portable way of using operating system dependent functionality. 翻译:提供一种方便的使用操作系统函数的方法. sys:This module provides access to some variables used or

  • python中如何打包用户自定义模块

    假设需要打包的模块文件名为my.py,打包模块需要新建的一个脚本setip.py,然后在脚本下输入如下的内容: from disutils.core import setup setup{name = 'my',version = '1.0',py_modules = ['my']} 以管理员身份运行cmd,进入my.py的目录,执行下面的命令即可打包: python setup.py sdist 运行后在该目录下方出现一个文件夹dist,进入这个文件夹,会出现一个my-1.0.zip文件. 将

  • python中翻译功能translate模块实现方法

    现如今,各个国家交流密切,通过翻译使我们打破了语言壁垒,而翻译在互联网上的存在也尤为普遍.python中执行翻译操作的包是translate包,通过下载安装translate包,使用translate模块可以在python中实现多种语言直接的相互翻译. 1.下载translate包 https://pypi.org/project/translate/ 2.使用pip安装translate包 pip install translate 3.使用translate模块实现翻译功能 from tra

随机推荐