我试图找到一个全面的指南,是否最好使用导入模块或从模块导入。我刚刚开始学习Python,我正试图从最佳实践开始。

基本上,我希望任何人都能分享他们的经验,其他开发者有什么偏好,以及避免任何陷阱的最佳方法是什么?


当前回答

导入模块——你不需要额外的努力从模块中获取另一个东西。它有缺点,如冗余输入

模块导入-更少的输入和更多的控制一个模块的项目可以访问。要使用模块中的新项,必须更新import语句。

其他回答

import module和from module import foo之间的区别主要是主观的。选择一个你最喜欢的,并始终如一地使用它。这里有几点可以帮助你做决定。

导入模块

优点: 更少地维护您的导入语句。不需要添加任何额外的导入就可以开始使用模块中的另一个项 缺点: 输入模块。Foo在你的代码中可能是乏味和冗余的(单调可以通过使用import module作为mo然后输入mo. Foo来最小化)

从模块导入foo

优点: 使用foo时输入更少 对可以访问模块的哪些项有更多的控制 缺点: 要使用模块中的新项,必须更新import语句 你失去了关于foo的上下文。例如,与math.ceil()相比,ceil()的作用就不太清楚了。

这两种方法都可以,但不要使用from module import *。

对于任何合理的大型代码集,如果您导入*,则可能会将其固化到模块中,无法删除。这是因为很难确定代码中使用的哪些项来自'module',这很容易让你认为你不再使用导入,但很难确定。

这里还有一个没有提到的区别。这是从http://docs.python.org/2/tutorial/modules.html逐字复制的

注意,当使用

from package import item

项目可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数、类或变量。import语句首先测试项目是否在包中定义;如果不是,则假定它是一个模块,并尝试加载它。如果找不到,则引发ImportError异常。

相反,当使用语法像

import item.subitem.subsubitem

除最后一项外,每一项都必须是一个包裹;最后一项可以是模块或包,但不能是前一项中定义的类、函数或变量。

有一些内置模块主要包含裸函数(base64, math, os, shutil, sys, time,…),将这些裸函数绑定到某个名称空间绝对是一个很好的实践,从而提高代码的可读性。想想看,如果没有命名空间,要理解这些函数的含义是多么困难:

copysign(foo, bar)
monotonic()
copystat(foo, bar)

当它们被绑定到某个模块时:

math.copysign(foo, bar)
time.monotonic()
shutil.copystat(foo, bar)

有时你甚至需要命名空间来避免不同模块之间的冲突(json. xml)。Load vs. pickle.load) 另一方面,有些模块包含大部分类(configparser, datetime, tempfile, zipfile,…),其中许多模块的类名不言自明:

configparser.RawConfigParser()
datetime.DateTime()
email.message.EmailMessage()
tempfile.NamedTemporaryFile()
zipfile.ZipFile()

因此,在代码中使用这些类和额外的模块名称空间是增加了一些新信息还是只是延长了代码,可能会有争论。

这里还有另一个细节,没有提到,与写入模块有关。虽然这可能不太常见,但我时不时地需要它。

由于Python中引用和名称绑定的工作方式,如果你想更新模块中的某个符号,请输入foo。Bar,从模块外部,并有其他导入代码“看到”的变化,你必须以某种方式导入foo。例如:

模块foo:

bar = "apples"

模块一:

import foo
foo.bar = "oranges"   # update bar inside foo module object

模块2:

import foo           
print foo.bar        # if executed after a's "foo.bar" assignment, will print "oranges"

但是,如果你导入的是符号名而不是模块名,这就行不通了。

例如,如果我在模块a中这样做:

from foo import bar
bar = "oranges"

没有代码在一个外部将看到bar作为“橙子”,因为我的bar设置只是影响模块a中的名称“bar”,它没有“到达”foo模块对象并更新它的bar。

import package
import module

对于import,令牌必须是一个模块(包含Python命令的文件)或一个包(sys。包含文件__init__.py的路径。)

当有子包时:

import package1.package2.package
import package1.package2.module

对文件夹(包)或文件(模块)的要求是相同的,但文件夹或文件必须在package2中,而package2必须在package1中,并且package1和package2都必须包含__init__.py文件。https://docs.python.org/2/tutorial/modules.html

使用import的from样式:

from package1.package2 import package
from package1.package2 import module

包或模块进入包含import语句的文件的命名空间为module(或包),而不是package1.package2.module。你总是可以绑定到一个更方便的名字:

a = big_package_name.subpackage.even_longer_subpackage_name.function

只有import的from样式允许你命名一个特定的函数或变量:

from package3.module import some_function

是允许的,但是

import package3.module.some_function 

是不允许的。