【发布时间】:2019-06-22 20:34:32
【问题描述】:
我需要知道如何设置 __init__.py 和导入,以便构建一个可以在整个包中使用完全限定名称的 python 项目。
该包将包含许多可能包含冲突名称的子包。包中包含的类将互为子类并包含对彼此的引用。该项目将被生成,因此使用完全限定名称将使生活变得更加简单。
这个示例项目代表了我的目标结构,但只包含一个子项目,而 IDE 似乎对它在运行时失败感到满意。
MyPackage/__init__.py
import SubPackage as SubPackage
MyPackage/SubPackage/__init__.py
from .FileB import ClassB
from .FileA import ClassA
MyPackage/SubPackage/FileA.py
from __future__ import absolute_import
import MyPackage
class ClassA(MyPackage.SubPackage.ClassB):
thingA: 'MyPackage.SubPackage.ClassA'
thingB: MyPackage.SubPackage.ClassB
def __init__(self):
self.thingA = None
self.thingB = None
def test(self):
self.thingA = MyPackage.SubPackage.ClassA()
self.thingB = MyPackage.SubPackage.ClassB()
MyPackage/SubPackage/FileB.py
from __future__ import absolute_import
import MyPackage
class ClassB(object):
nextB: 'MyPackage.SubPackage.ClassB'
def __init__(self):
self.nextB= None
def test(self):
self.nextB= MyPackage.SubPackage.ClassB()
test.py
import MyPackage
x = MyPackage.SubPackage.ClassA()
错误
File "C:\temp\Test.py", line 3, in <module>
import GeneratedLx
File "C:\temp\MyPackage\__init__.py", line 1, in <module>
import Bs as Bs
File "C:\temp\MyPackage\SubPackage\__init__.py", line 12, in <module>
from .FileA import ClassA
File "C:\temp\MyPackage\SubPackage\FileA.py", line 5, in <module>
class ClassA(MyPackage.SubPackage.ClassB):
AttributeError: module 'MyPackage' has no attribute 'SubPackage'
【问题讨论】:
-
为什么需要完全限定所有内容?为什么还有这么多模块?如果问题中的代码具有代表性,则您的模块非常短。您通常只在每个模块中包含几个类,从而避免大量导入。有理由不这样做吗?此外,除非存在名称冲突,否则最好使用较短的引用。
-
可能有 100 个模块和最多约 5 个子包。子包中的类可以相互关联(从另一个子包中的类派生)并使用其他子包中的类。因此存在名称冲突的可能性,因此最好对名称进行完全限定。
-
离开名称链
MyPackage应该使您的变量足够合格以避免冲突,并消除引用问题(我认为是鸡和蛋)。在“FileA”和 B 中,只需from MyPackage import Submodule并跳过名称中的MyPackage.。 FTR 调用这些长属性链可能会对性能产生明显影响(attr 调用并不快)。 -
@Sproty 听起来你真的会从将你的模块合并到更少的模块中受益匪浅。 特别是当类相互依赖时,将它们包含在同一个模块中要简单得多。模块和包不用于创建详细的分类。它们用于提供一起工作的大量函数、类和变量,或者用于避免名称冲突。如果你在一个包中有数百个模块,那么你可能正在做一些非 Pythonic 的事情。在您的顶级包中,考虑别名而不是完全限定。
-
源数据(将生成这些类)被分解为多个“命名空间”,因此相同的名称可能出现在 2 个命名空间中。我认为 SubPackage 将是每个命名空间的好容器。如果每个命名空间中的类是独立的,那么每个子包可以是一个单独的模块,但是每个子包中的类之间可能存在相互关系,即 nsA:cls1 派生自 nsB:cls2 派生自 nsA:cls3。一种保证它们以正确顺序定义的方法是拆分 1 个类/模块,除非 Python 可以进行前向声明?