繁体   English   中英

是否可以将Python类/函数安排到包命名空间中,从而避免使用模块命名空间?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM