[英]Is it possible to arrange Python classes/functions into package namespaces, avoiding the module namespace?
让我们说我的文件结构如下:
.
├── a
│ ├── b
│ │ ├── ClassB0.py
│ │ ├── ClassB1.py
│ │ ├── functionB.py
│ │ └── __init__.py
│ ├── ClassA0.py
│ ├── ClassA1.py
│ ├── functionA.py
│ └── __init__.py
└── test.py
这个想法是每个文件包含一个类或一个函数 - 例如ClassB0.py
具有class ClassB0: ...
并且functionA.py
具有def functionA(): ...
但是,我希望能够使用前缀访问这些类/函数,但只能访问与文件夹相关的前缀。 所以我希望能够在这个树的任何地方做任何类似的事情(假设Python始终在顶级文件夹中启动):
a.b.functionB()
a.b.ClassB1()
a.ClassA1()
a.functionA()
我想避免的是使用文件夹和文件的前缀:
a.b.functionB.functionB()
a.b.ClassB1.ClassB1()
a.ClassA1.ClassA1()
a.functionA.functionA()
我已经尝试通过在__init__.py
文件中放入以下代码来实现这一点:
from .ClassB0 import ClassB0
from .ClassB1 import ClassB1
from .functionB import functionB
这适用于一个“级别”(所以没有b/
)或非常简单的类。 但是扭曲的是ClassB1
需要ClassB0
,这会通过引起循环依赖来打破整个事情(至少我认为这是我问题的根本原因)。 如果我尝试运行我的脚本,我会收到这样的错误:
$ python test.py
Traceback (most recent call last):
File "test.py", line 1, in <module>
import a
File "/home/freddie/test/testpy/a/__init__.py", line 3, in <module>
from .functionA import functionA
File "/home/freddie/test/testpy/a/functionA.py", line 1, in <module>
import a.b
File "/home/freddie/test/testpy/a/b/__init__.py", line 2, in <module>
from .ClassB1 import ClassB1
File "/home/freddie/test/testpy/a/b/ClassB1.py", line 3, in <module>
class ClassB1(a.b.ClassB0):
AttributeError: module 'a' has no attribute 'b'
作为参考,这是这些文件的完整代码。
test.py
import a
a.functionA()
a/ClassA0.py
class ClassA0:
def __init__(self):
print('ClassA0')
a/ClassA1.py
import a
class ClassA1(a.ClassA0):
def __init__(self):
a.ClassA0.__init__(self)
print('ClassA1')
a/functionA.py
import a.b
import a
def functionA():
a.ClassA1()
a.b.functionB()
a/__init__.py
from .ClassA0 import ClassA0
from .ClassA1 import ClassA1
from .functionA import functionA
a/b/ClassB0.py
class ClassB0:
def __init__(self):
print('ClassB0')
a/b/ClassB1.py
import a.b
class ClassB1(a.b.ClassB0):
def __init__(self):
a.b.ClassB0.__init__(self)
print('ClassB1')
a/b/functionB.py
import a.b
def functionB():
a.b.ClassB1()
a/b/__init__.py
from .ClassB0 import ClassB0
from .ClassB1 import ClassB1
from .functionB import functionB
有什么方法可以解决这个问题(不使用Python导入系统中的低级别黑客攻击)? 也许我已经习惯了C ++命名空间的工作方式,而这在Python中无法完成?
正如我之前所写,我正在尝试使用一个允许我使用完全限定名称的结构,但没有模块的名称,所以只有包名。 我也想避免将我的所有类/函数重命名为类似A_B_ClassB1
,因为这看起来不太好(我不是Python专家,所以也许我使用的文件结构或我的方法尝试(在__init__.py
文件中导入)并不好 - 我愿意接受任何允许我使用像abClassB1
这样的名字的abClassB1
,但是在某种形式下保持类似组织在文件夹/文件级别。
你有一个好主意,但你忽略了Python所构建的功能。
Python包是以某种方式相关的模块的集合。
Python模块是一个单独的文件,它包含一组一起工作的类和/或函数。
每个文件不应该有类或函数。 那不是好设计。
试图搞乱导入系统使abClassB1
引用a/b/ClassB1
文件中的a/b/ClassB1
类是混乱的业务。 这不是导致错误的直接原因,但它引入了许多其他复杂情况,并且通常难以解决问题。
我建议至少命名类和文件不同的东西,比如_ClassB1.py
文件和ClassB1
类,这样你就可以单独引用类和模块而不会产生歧义。 这很重要。
在其中点a/b/ClassB1.py
试图指abClassB0
,对于模块对象ab
模块并未实际分配给b
的属性a
模块对象。 只有在__init__.py
for ab
完成执行后才会发生这种情况,并且__init__.py
仍在继续。 在ab
属性分配发生之前,您不能引用ab
。
除了属性赋值问题之外, ClassB1.py
还假设abClassB0
是类而不是模块,这意味着它假设from .ClassB0 import ClassB0
出现在from .ClassB1 import ClassB1
之前__init__.py
from .ClassB1 import ClassB1
。 这引入了导入排序要求,如果ab
问题没有首先发生,则会导致其他令人讨厌的头痛。
要解决此问题,您可以使用相对导入来访问兄弟模块及其内容,而无需尝试访问ab
属性。 不幸的是,这会使你的结构变得更加混乱,因为它的含义就像from . import ClassB0
在ClassB1.py
from . import ClassB0
取决于__init__.py
是否已执行相同的导入。 如果您将文件名更改为与类名不冲突,则事情就会变得更加混乱:
# _ClassB1.py
from ._ClassB0 import ClassB0
class ClassB1(ClassB0):
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.