我试图找到一个全面的指南,是否最好使用导入模块或从模块导入。我刚刚开始学习Python,我正试图从最佳实践开始。
基本上,我希望任何人都能分享他们的经验,其他开发者有什么偏好,以及避免任何陷阱的最佳方法是什么?
我试图找到一个全面的指南,是否最好使用导入模块或从模块导入。我刚刚开始学习Python,我正试图从最佳实践开始。
基本上,我希望任何人都能分享他们的经验,其他开发者有什么偏好,以及避免任何陷阱的最佳方法是什么?
当前回答
有很多答案,但没有一个提到测试(使用unittest或pytest)。
博士tl;
对外部模块使用import foo来简化测试。
艰难的方式
从模块中单独导入类/函数(从foo import bar中)会使红绿重构周期变得冗长乏味。例如,如果我的文件看起来像
# my_module.py
from foo import bar
class Thing:
def do_thing(self):
bar('do a thing')
我的测试是
# test_my_module.py
from unittest.mock import patch
import my_module
patch.object(my_module, 'bar')
def test_do_thing(mock_bar):
my_module.Thing().do_thing()
mock_bar.assert_called_with('do a thing')
乍一看,这似乎很棒。但是如果我想在不同的文件中实现Thing类会发生什么呢?我的结构将不得不像这样改变……
# my_module.py
from tools import Thing
def do_thing():
Thing().do_thing()
# tools.py
from foo import bar
class Thing:
def do_thing(self):
bar('do a thing')
# test_my_module.py
from unittest.mock import patch
import my_module
import tools # Had to import implementation file...
patch.object(tools, 'bar') # Changed patch
def test_do_thing(mock_bar):
my_module.do_thing() # Changed test (expected)
mock_bar.assert_called_with('do a thing')
不幸的是,由于我使用from foo import bar,我需要更新我的补丁来引用工具模块。从本质上讲,由于我的测试对实现了解太多,因此要进行这个重构,需要更改的内容要比预期的多得多。
更好的方法
使用import foo,我的测试可以忽略模块是如何实现的,而只是对整个模块打补丁。
# my_module.py
from tools import Thing
def do_thing():
Thing().do_thing()
# tools.py
import foo
class Thing:
def do_thing(self):
foo.bar('do a thing') # Specify 'bar' is from 'foo' module
# test_my_module.py
from unittest.mock import patch
import my_module
patch('foo') # Patch entire foo module
def test_do_thing(mock_foo):
my_module.do_thing() # Changed test (expected)
mock_foo.bar.assert_called_with('do a thing')
测试知道的实现细节越少越好。这样,如果您提出了更好的解决方案(使用类而不是函数,使用额外的文件来分离思想,等等),那么在您的测试中需要更改的内容就会更少,以适应重构。
其他回答
import module
当您将使用模块中的许多函数时是最好的。
from module import function
如果只需要函数,而希望避免使用模块中的所有函数和类型污染全局名称空间,则最好使用此方法。
import module和from module import foo之间的区别主要是主观的。选择一个你最喜欢的,并始终如一地使用它。这里有几点可以帮助你做决定。
导入模块
优点: 更少地维护您的导入语句。不需要添加任何额外的导入就可以开始使用模块中的另一个项 缺点: 输入模块。Foo在你的代码中可能是乏味和冗余的(单调可以通过使用import module作为mo然后输入mo. Foo来最小化)
从模块导入foo
优点: 使用foo时输入更少 对可以访问模块的哪些项有更多的控制 缺点: 要使用模块中的新项,必须更新import语句 你失去了关于foo的上下文。例如,与math.ceil()相比,ceil()的作用就不太清楚了。
这两种方法都可以,但不要使用from module import *。
对于任何合理的大型代码集,如果您导入*,则可能会将其固化到模块中,无法删除。这是因为很难确定代码中使用的哪些项来自'module',这很容易让你认为你不再使用导入,但很难确定。
有很多答案,但没有一个提到测试(使用unittest或pytest)。
博士tl;
对外部模块使用import foo来简化测试。
艰难的方式
从模块中单独导入类/函数(从foo import bar中)会使红绿重构周期变得冗长乏味。例如,如果我的文件看起来像
# my_module.py
from foo import bar
class Thing:
def do_thing(self):
bar('do a thing')
我的测试是
# test_my_module.py
from unittest.mock import patch
import my_module
patch.object(my_module, 'bar')
def test_do_thing(mock_bar):
my_module.Thing().do_thing()
mock_bar.assert_called_with('do a thing')
乍一看,这似乎很棒。但是如果我想在不同的文件中实现Thing类会发生什么呢?我的结构将不得不像这样改变……
# my_module.py
from tools import Thing
def do_thing():
Thing().do_thing()
# tools.py
from foo import bar
class Thing:
def do_thing(self):
bar('do a thing')
# test_my_module.py
from unittest.mock import patch
import my_module
import tools # Had to import implementation file...
patch.object(tools, 'bar') # Changed patch
def test_do_thing(mock_bar):
my_module.do_thing() # Changed test (expected)
mock_bar.assert_called_with('do a thing')
不幸的是,由于我使用from foo import bar,我需要更新我的补丁来引用工具模块。从本质上讲,由于我的测试对实现了解太多,因此要进行这个重构,需要更改的内容要比预期的多得多。
更好的方法
使用import foo,我的测试可以忽略模块是如何实现的,而只是对整个模块打补丁。
# my_module.py
from tools import Thing
def do_thing():
Thing().do_thing()
# tools.py
import foo
class Thing:
def do_thing(self):
foo.bar('do a thing') # Specify 'bar' is from 'foo' module
# test_my_module.py
from unittest.mock import patch
import my_module
patch('foo') # Patch entire foo module
def test_do_thing(mock_foo):
my_module.do_thing() # Changed test (expected)
mock_foo.bar.assert_called_with('do a thing')
测试知道的实现细节越少越好。这样,如果您提出了更好的解决方案(使用类而不是函数,使用额外的文件来分离思想,等等),那么在您的测试中需要更改的内容就会更少,以适应重构。
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
是不允许的。
我自己的答案主要取决于首先,我将使用多少不同的模块。如果我只打算用一两个,我会经常用from…import,因为它在文件的其余部分减少了击键,但如果我要使用许多不同的模块,我更喜欢只使用import,因为这意味着每个模块引用都是自文档化的。我可以看到每个符号的来源,而不需要到处寻找。
通常我更喜欢简单导入的自文档风格,只更改from..当我必须输入模块名的次数增加到10到20次时,即使只有一个模块被导入。