python导入 - 公共或私人约定

时间:2016-06-13 18:59:19

标签: python import conventions

在Python约定中,模块的导入是否应该被视为其公共接口的一部分?

我有一些代码可以做到这一点:

foo.py

from a import b

bar.py

from foo import b

我正在尝试决定是否重构bar.py直接从a导入b。我想在某些情况下你可能希望foo.py控制bar.py使用的b的实现。但如果情况并非如此,那么让两个模块以同样的方式导入它不是更好的做法吗?

4 个答案:

答案 0 :(得分:2)

  

在Python惯例中,模块的导入是否应该被视为其公共接口的一部分?

模块的公共API是模块记录其公共API的任何内容。如果模块foo记录了它提供的b,则b是其公共API的一部分,无论b是在foo中实际定义还是从其他地方导入。

许多模块将代码分成多个文件,并将所有部分一起导入一个模块。例如,collections模块将其部分代码放在C _collections模块中并执行

from _collections import deque, defaultdict

dequedefaultdict明确地成为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__模块。