Use 'import module' or 'from module import'?
我试图找到一个全面的指南来说明使用
基本上,我希望任何人都能分享他们的经验,其他开发人员有什么偏好,以及什么是最好的方法来避免路上出现任何问题?
- 赞成的意见:
- 少维护你的
import 报表。不需要添加任何其他导入即可开始使用模块中的其他项
- 少维护你的
- 欺骗:
- 在代码中键入
module.foo 可能是冗长的(可以通过使用import module as mo 来最小化冗长,然后键入mo.foo )
- 在代码中键入
- 赞成的意见:
- 使用
foo 的输入较少 - 对模块中哪些项可以访问的更多控制
- 使用
- 欺骗:
- 要使用模块中的新项目,您必须更新您的
import 语句。 - 你失去了关于
foo 的上下文。例如,与math.ceil() 相比,ceil() 的作用还不太清楚。
- 要使用模块中的新项目,您必须更新您的
任何一种方法都可以接受,但不要使用
对于任何合理的大代码集,如果您
这里还有另一个细节,没有提到,与写入模块有关。当然,这可能并不常见,但我不时需要它。
由于引用和名称绑定在python中的工作方式,如果您希望从模块外部更新模块中的某些符号(比如foo.bar),并让其他导入代码"see"发生更改,则必须以某种方式导入foo。例如:
模块FO:
1 | bar ="apples" |
模块A:
1 2 | import foo foo.bar ="oranges" # update bar inside foo module object |
模块B:
1 2 | import foo print foo.bar # if executed after a's"foo.bar" assignment, will print"oranges" |
但是,如果导入符号名而不是模块名,这将不起作用。
例如,如果我在模块A中这样做:
1 2 | from foo import bar bar ="oranges" |
A之外没有代码会将条形图视为"橙色",因为我对条形图的设置只影响了模块A内的名称"条形图",它没有"触及"FOO模块对象并更新其"条形图"。
尽管很多人已经解释过
导入
例如:
导入
例如:
导入
如
现在让我们看看我们什么时候做
1 2 | >>> import sys >>> import os.path |
检查名称为
1 2 3 4 | >>> sys.modules['os'] <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> sys.modules['os.path'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> |
用
1 2 3 4 5 6 7 8 9 | >>> globals()['os'] <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> locals()['os'] <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> globals()['os.path'] Traceback (most recent call last): File"<stdin>", line 1, in <module> KeyError: 'os.path' >>> |
从上面的示例中,我们发现只有
1 2 3 4 5 6 7 | >>> os <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> os.path <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> |
但不是
1 2 3 4 5 | >>> path Traceback (most recent call last): File"<stdin>", line 1, in <module> NameError: name 'path' is not defined >>> |
一旦从locals()命名空间中删除
1 2 3 4 5 6 7 8 9 10 | >>> del locals()['os'] >>> os Traceback (most recent call last): File"<stdin>", line 1, in <module> NameError: name 'os' is not defined >>> os.path Traceback (most recent call last): File"<stdin>", line 1, in <module> NameError: name 'os' is not defined >>> |
现在我们来谈谈
1 2 | >>> import sys >>> from os import path |
用
1 2 3 4 | >>> sys.modules['os'] <module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'> >>> sys.modules['os.path'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> |
我们发现,在
好的,让我们检查一下在
1 2 3 4 5 6 7 8 9 | >>> globals()['path'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> locals()['path'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> globals()['os'] Traceback (most recent call last): File"<stdin>", line 1, in <module> KeyError: 'os' >>> |
您可以使用名称
1 2 3 4 5 6 7 | >>> path <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> os.path Traceback (most recent call last): File"<stdin>", line 1, in <module> NameError: name 'os' is not defined >>> |
让我们从
1 2 3 4 5 6 | >>> del locals()['path'] >>> path Traceback (most recent call last): File"<stdin>", line 1, in <module> NameError: name 'path' is not defined >>> |
最后一个使用别名的示例:
1 2 3 4 5 6 | >>> from os import path as HELL_BOY >>> locals()['HELL_BOY'] <module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> globals()['HELL_BOY'] <module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'> >>> |
未定义路径:
1 2 3 4 5 | >>> globals()['path'] Traceback (most recent call last): File"<stdin>", line 1, in <module> KeyError: 'path' >>> |
这两种方法都有一个原因:有时一种方法比另一种方法更合适。
import module :当您使用模块中的许多位时很好。缺点是您需要用模块名限定每个引用。from module import ... :很好,导入的项目可以直接使用,没有模块名称前缀。缺点是你必须列出你所使用的每一件事情,并且在代码中不清楚事情的来源。
使用哪一个取决于哪一个使代码清晰易读,并且与个人偏好有着更多的关系。我倾向于使用
我个人总是用
1 | from package.subpackage.subsubpackage import module |
然后访问所有内容
1 2 | module.function module.modulevar |
等等。原因是,在进行短调用的同时,您清楚地定义了每个例程的模块名称空间,如果您必须搜索源中给定模块的用法,这是非常有用的。
不用说,不要使用import*,因为它会污染您的名称空间,并且它不会告诉您给定函数的来源(来自哪个模块)
当然,如果两个不同的包中的两个不同模块具有相同的模块名,例如
1 2 | from package1.subpackage import module from package2.subpackage import module |
在这种情况下,当然会遇到麻烦,但是有一个强烈的提示,即您的包布局有缺陷,您必须重新考虑它。
1 | import module |
当您使用模块中的许多功能时,最好使用。
1 | from module import function |
当您只需要
这里还有一个没有提到的区别。这是从http://docs.python.org/2/tutorial/modules.html逐字复制的。
注意使用时
1 | from package import item |
项可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数、类或变量。import语句首先测试该项是否在包中定义;如果不是,则假定它是一个模块,并尝试加载它。如果找不到它,将引发importError异常。
相反,当使用类似
1 | import item.subitem.subsubitem |
除最后一项之外的每个项都必须是包;最后一项可以是模块或包,但不能是在前一项中定义的类、函数或变量。
我刚刚发现这两种方法之间还有一个微妙的区别。
如果模块
1 | from itertools import count |
那么,模块
1 2 | import foo foo.count() |
如果
1 | import itertools |
这个错误仍然是可能的,但不太可能发生。
1 2 | import foo foo.itertools.count() |
这给我带来了一些麻烦。我有一个模块错误地从一个没有定义它的模块导入了一个异常,只从其他模块导入了它(使用
1 2 | import package import module |
对于
当存在子包时:
1 2 | import package1.package2.package import package1.package2.module |
文件夹(包)或文件(模块)的要求相同,但文件夹或文件必须在
采用进口
1 2 | from package1.package2 import package from package1.package2 import module |
包或模块以
1 | a = big_package_name.subpackage.even_longer_subpackage_name.function |
只有
1 | from package3.module import some_function |
是允许的,但是
1 | import package3.module.some_function |
是不允许的。
为了补充人们对
由于我也是一个初学者,我将尝试用一种简单的方式来解释这一点:在python中,我们有三种类型的
1。通用导入:
1 | import math |
这种类型的导入是我个人最喜欢的,这种导入技术的唯一缺点是,如果需要使用任何模块的函数,则必须使用以下语法:
1 | math.sqrt(4) |
当然,它增加了打字的工作量,但是作为一个初学者,它将帮助您跟踪与之相关的模块和函数(一个好的文本编辑器将显著减少打字的工作量,建议使用)。
使用此import语句可以进一步减少键入工作:
1 | import math as m |
现在,您可以使用
2。函数导入:
1 | from math import sqrt |
如果代码只需要访问模块中的单个或几个函数,那么这种类型的导入最适合,但是对于使用模块中的任何新项,必须更新import语句。
三。通用进口:
1 | from math import * |
虽然它大大减少了输入的工作量,但不推荐这样做,因为它会用模块中的各种函数填充代码,并且它们的名称可能与用户定义函数的名称冲突。例子:
如果您有一个名为sqrt的函数,并且导入math,那么您的函数是安全的:有sqrt,有math.sqrt。但是,如果从math import*执行,则会遇到一个问题:即两个同名的不同函数。来源:codecademy我自己对此的答案主要取决于第一,我将使用多少不同的模块。如果我只使用一两个,我经常使用
通常我更喜欢简单导入的自我记录风格,只会从..改为..当我必须键入模块名的次数超过10到20次时导入,即使只有一个模块正在导入。
导入模块-您不需要额外的工作来从模块中获取其他内容。它有一些缺点,比如重复输入
模块导入自-更少的键入和更多的控制可以访问模块中的哪些项。若要使用模块中的新项,必须更新导入语句。