在Python约定中,模块的导入是否应该被视为其公共接口的一部分?
我有一些代码可以做到这一点:
foo.py :
from a import b
bar.py :
from foo import b
我正在尝试决定是否重构bar.py直接从a导入b。我想在某些情况下你可能希望foo.py控制bar.py使用的b的实现。但如果情况并非如此,那么让两个模块以同样的方式导入它不是更好的做法吗?
答案 0 :(得分:2)
在Python惯例中,模块的导入是否应该被视为其公共接口的一部分?
模块的公共API是模块记录其公共API的任何内容。如果模块foo
记录了它提供的b
,则b
是其公共API的一部分,无论b
是在foo
中实际定义还是从其他地方导入。
许多模块将代码分成多个文件,并将所有部分一起导入一个模块。例如,collections
模块将其部分代码放在C _collections
模块中并执行
from _collections import deque, defaultdict
deque
和defaultdict
明确地成为collections
公共API的一部分。
如果某个模块导入的东西不应该是其公共API的一部分,那么import thing as _thing
通常是一个好主意,在其上加上一个下划线表示导入事情是一个实施细节。
答案 1 :(得分:2)
文档观点。惯例是,不以下划线开头的所有内容都是公开的。如果要将导入符号标记为私有,请使用下划线(如from a import b as _b
)对其进行别名。还有另一种选择。您可以使用__all__
来声明您认为公开的符号。尽管从技术上讲它只影响from module import *
,但它也是一个很好的意图声明。
依赖性观点。我不建议在没有充分理由的情况下使依赖图变得复杂,因为否则在开发过程中稍后有更高的机会偶然发现循环导入问题。
根据Zen of Python,显式优于隐式,简单优于复杂。因此,如果模块a
提供符号b
,那么使用b
的所有模块都可以从a
导入它。
答案 2 :(得分:0)
忍者模式模块定义
public class WhateverTheseParametersAre
{
public string P1 {get;set;}
public string P2 {get;set;}
public bool P3 {get;set;}
}
答案 3 :(得分:0)
PEP 8在此提供了一些指导。
导入的名称应始终被视为实现细节。其他模块不得依赖对此类导入名称的间接访问,除非它们是包含模块的API中明确记录的一部分,例如os.path或从子模块公开功能的程序包__init__模块。