unu*_*tbu 67 python python-import
我们from module import function称之为FMIF编码风格.
我们import module称之为IM编码风格.
我们from package import module称之为FPIM编码风格.
为什么IM + FPIM被认为是比FMIF更好的编码风格?(请参阅此帖子以获取此问题的灵感.)
以下是一些让我更喜欢FMIF而非IM的标准:
chisquare(...)看起来比可读性更强 scipy.stats.stats.chisquare(...).虽然这是一个主观标准,但我认为大多数人会同意.
function从alt_module不是module我需要改变只有一条线路:from alt_module import function.如果我使用IM,我需要更改许多行代码.
我对IM + FPIM可能比FMIF更好的所有原因感兴趣,但特别是,我有兴趣详细说明这里提到的以下几点:
IM的优点:
非常感谢.
Ale*_*lli 45
您为IM/FPIM列出的否定通常可以通过适当使用as条款来改善. from some.package import mymodulewithalongname as mymod可以有用地缩短代码并增强其可读性,如果重命名mymodulewithalongname为somethingcompletelydifferent明天,则该as子句可以用作单个语句进行编辑.
考虑你的pro-FMIF第3点(称之为R用于重定向)与你的pro-FPIM第2点(称之为F的灵活性):R相当于促进模块边界完整性的丧失,而F则强化它.模块中的多个函数,类和变量通常旨在协同工作:它们不应独立地切换到不同的含义.例如,考虑模块random及其功能,seed并且uniform:如果您只将其中一个的导入切换到另一个模块,那么您将打破调用seed和调用结果之间的正常连接uniform.当一个模块设计得很好,具有凝聚力和完整性时,R便于打破模块的界限实际上是一个负面的 - 它可以让你更容易做一些你最好不做的事情.
反之亦然,F是能够通过模块化协调切换耦合函数,类和变量(通常是属于一起的实体).例如,为了使测试可重复(FPIM亲点1),你嘲笑都seed和random中random模块,如果你的代码如下FPIM,你所有的设置,协调保障; 但是如果你有直接导入函数的代码,你必须搜索每个这样的模块并反复重复模拟.使测试完全可重复通常还需要对日期和时间函数进行"协调from datetime import datetime模拟" - 如果您在某些模块中使用,则需要查找并模拟它们(以及所有正在执行的操作from time import time,等等)以确保所有当系统的各个部分问"现在几点了?"时收到的时间.完全一致(如果你使用FPIM,你只需要模拟两个相关的模块).
我喜欢FPIM,因为那里真的没有太多的附加值用乘法合格的名称,而不是一个单独合格的一个(而barenames和合格的名称之间的差异是巨大的 -你会得到这样一个合格的名字更多的控制,无论是单或者乘以比你可能用的名字!).
好吧,不能把所有工作日用于回应你的每一点 - 你的问题可能应该是六个问题;-).我希望这至少解决"为什么F比R好"和一些模拟/测试问题 - 它归结为保留和增强精心设计的模块化(通过F)而不是破坏它(通过R).
Dan*_*man 17
关于这一点的经典文本经常来自Fredrik Lundh,即effbot.他的建议是:总是使用导入 - 除非你不应该.
换句话说,要明智.就个人而言,我发现任何深层的模块都倾向于通过引入from x.y.z import a- 主要的例子是Django模型.但与其他任何东西一样,它都是一个风格问题,你应该有一个一致的 - 特别是对于模块datetime,其中模块和它包含的类被称为相同的东西.你需要写作datetime.datetime.now()还是只是datetime.now()?(在我的代码中,始终是前者.)
问题列表中的第1项和第2项似乎是同一个问题.Python的动态特性意味着无论您使用哪种方法,替换模块命名空间中的项都相当简单.如果模块中的一个函数引用另一个函数(即您要模拟的函数),则会遇到困难.在这种情况下,导入模块而不是函数意味着您可以做到module.function_to_replace = myreplacementfunc并且一切都透明地工作 - 但这通过FPIM和通过IM一样容易.
我也不明白第3项与任何事情有什么关系.但是,我认为你的第4项是基于一点点误解.您提供的任何方法都不会"污染您的命名空间".这样做是什么from module import *,你根本不知道你要导入什么,所以函数可以出现在你的代码中,而不会给读者带来任何线索.那太可怕了,应该不惜一切代价避免.
这里有很棒的答案(我全都赞成),以下是我对此事的看法:
首先,解决每个子弹:
(据称)FMIF的优点:
也许,但模块名称通常足够短,所以这是不相关的.当然,还有datetime,而且os,re,sys,等.而Python有免费线内休息{ [ (.对于嵌套模块,总是as在IM和FPIM中
强烈反对.在阅读外国代码(或几个月后我自己的代码)时,很难知道每个函数的来源.合格的名称使我免于从2345行到模块声明标题.它还为你提供了背景:" chisquare那是什么?哦,它来自scypy哪里?好吧,一些与数学相关的东西".而且,再一次,您可以随时缩写scipy.stats.stats as scypyst.scypyst.chisquare(...)足够短,具有合格名称的所有好处.
import os.path as osp 另一个很好的例子,考虑到在一次调用中将3个或更多函数链接在一起非常常见:join(expanduser(),basename(splitext()))等.
您想多久重新定义一个函数而不是整个模块?应保留模块边界和功能协调,Alex已经深入解释了这一点.对于大多数(所有?)现实场景,如果alt_module.x是可行的替代品module.x,那么可能alt_module本身就是替代品module,因此IM和FPIM就像FMIF一样是单行的,只要你使用它as.
实际上,as是减轻前两个问题(和第三个)的问题,而不是FPIM.您也可以使用IM: import some.long.package.path.x as x与FPIM相同的结果.
所以以上都不是FMIF的真正优点.我更喜欢IM/FPIM的原因是:
为了简单和一致,当我导入IM或FPIM时,我总是导入模块,而不是模块中的对象.记住FMIF可以(ab-)用于导入函数,类,变量甚至其他模块!想想乱七八糟的东西from somemodule import sys, somevar, os, SomeClass, datetime, someFunc.
此外,如果您需要模块中的多个对象,FMIF将比IM或FPIM污染您的命名空间,无论您要使用多少个对象,它都将使用单个名称.这样的对象将具有一个合格的 名称,这是一个专业人士,而不是一个骗局:正如我在问题2中所说的,恕我直言,它提高了可读性.
这一切都归结为一致性,简洁性,组织性."导入模块,而不是对象"是一个很好的,易于思考的模型.
像Alex Martelli一样,我喜欢as在导入函数时使用.
我做的一件事是在从同一模块导入的所有函数上使用一些前缀:
from random import seed as r_seed
from random import random as r_random
Run Code Online (Sandbox Code Playgroud)
r_seed类型比键入更短random.seed但有些保留模块边界.随便看看你的代码的人可以看到r_seed()并且r_random()有机会认识到它们是相关的.
当然,您可以随时做到:
import random as r
Run Code Online (Sandbox Code Playgroud)
然后使用r.random()和r.seed(),这可能是这种情况下的理想折衷方案.当我从模块导入一个或两个函数时,我只使用前缀技巧.当我想使用同一模块中的许多函数时,我将导入模块,也许是as为了缩短名称.