簡體   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