簡體   English   中英

Python名稱空間元素的可見性(相對於正確的包結構)

[英]Python namespace elements visibility (vs proper package structure)

Python3

試圖找到答案,但失敗了。 首先,我將介紹該代碼段,然后說明為什么要這樣做,以及要實現的目標。 也許看起來這種方法是“壞方法”。 因此,這個半雙主題的話題,首先是因為我想知道為什么這個代碼片段不起作用,其次是我想知道這種方法是否正確。

所以:

class Namespace:
    def some_function():
        pass

    class SomeClass:
        fcnt = some_function

由於以下原因,這將無法工作:

NameError: name 'some_function' is not defined

我要實現的是代碼和文件結構的可讀性。

上面的示例是一個我在Pyramid項目中使用的代碼段(不是這個代碼段,但是看起來像這樣)。

我的項目樹如下所示:

my_project
├── models
│   ├── __init__.py
│   └── some_model.py
├── schemas
│   ├── __init__.py
│   ├── some_schema.py
│   └── some_other_schema.py
...
├── views
│   ├── __init__.py
│   └── some_view.py
└── __init__.py

我想要實現的是干凈的架構/模型/視圖導入。

some_schema.py文件駐留class SomeSchema ,在some_other_schema.py class SomeOtherSchema

使用上面的代碼片段,我可以from my_project.schemas.some_schema import Schema

並像Schema.SomeSchema()一樣使用它

我對包和import有點迷失了。 如何構造一個干凈的結構(每個文件一個架構)並仍然能夠使用Schema名稱空間? (在C ++中,我只是將每個類都放在Schema名稱空間中,這就是為什么在上面的代碼段中這樣做。但是!在C ++中起作用的內容也許不應該在python中使用,對吧?)。

感謝您提前答復。

編輯:好的,我已經做了一些測試(我認為我已經完成了,但是看起來還沒有..)。

  1. from my_project.schemas.some_schema import Schema使用from my_project.schemas.some_schema import Schema中的另一個from my_project.schemas.some_other_schema import Schema會在第二個導入中導致第一個導入。 因此,如果第一次導入后我能夠使用x = Schema.SomeSchema()不是第二次導入后,因為class Schema被覆蓋,我將無法執行此操作。 是的,正如Erik所說的-類不是名稱空間。 得到它了!
  2. 在我的第一個代碼段中,是的,我應該使用fnct = Namespace.some_function 奇怪的是-它有效。 我的金字塔代碼中的語句相同,只是有所不同。 some_function具有@colander.deferred裝飾器。 實際上看起來像這樣:

     class Schema: @colander.deferred def deferred_some_function(node, kw): something = kw.get("something", []) return deform.widget.SelectWidget(values=something, multiple=True) class SomeSchema(colander.MappingSchema): somethings = colander.SchemaNode(colander.Set(), widget=Schema.deferred_some_function) 

    我得到NameError: name 'Schema' is not defined

  3. 回到包格式。 有了這個:

     ### another/file.py from foo.bar.schema import SomeSchema # do something with SomeSchema: smth = SomeSchema() smth.fcnt() 

    我必須創建一個模塊foo/bar/schema.py在其中必須放置所有SomeXSchema類。 如果我有很多的話,那我就想通過拆分SomeXSchema來消除無法讀取的故障-每個文件一個。 我可以以某種方式完成此操作嗎? 我想例如稱此類: User 這就是事情。 也許我做錯了嗎? 我想有一個名為類Userschema 命名空間和命名的類Usermodel 的命名空間 我不是嗎 也許我應該使用前綴? class SchemaUser class ModelUserclass ModelUser 我想通過使用模塊/軟件包來避免這種情況。 如果我要使用: import foo.bar.schema那么我必須像x = foo.bar.schema.User()一樣使用它,對嗎? 沒有辦法像x = schema.User()那樣使用它? 抱歉,我被卡住了,我的大腦被固定了。 也許我需要休息一下以重新看一下?

    另一個編輯(僅適用於要點3)

    我做了更多的研究。 答案是使它像這樣:

     ## file: myproject/schemas/__init__.py from .some_schema import SomeSchema from .some_other_schema import SomeOtherSchema 

    然后用法如下:

     ## some file using it import myproject.schemas as schema s1 = schema.SomeSchema() s2 = schema.SomeOtherSchema() 

    會是legis artis嗎?

  4. 如果有人認為應該更改主題,請繼續,給我一些更有意義的信息,我將不勝感激。

您正在通過嘗試做自己想做的事情向上游游泳。

類用於定義新的數據類型,而不是將代碼的相關部分組合在一起的一種手段。 模塊非常適合於此,由於問題標題中的“(相對於正確的包裝結構)”部分,我想您知道的很好。

模塊也可以作為對象導入,因此可以實現所需的功能:

### foo/bar/schema.py
def some_function():
    pass
class SomeSchema:
    fcnt = some_function


### another/file.py
from foo.bar import schema

# do something with SomeSchema:
smth = schema.SomeSchema()
smth.fcnt()

...雖然將類直接導入到這樣的范圍內也是很典型的( SomeSchema ,在導入之后能夠引用SomeSchema而不是schema.SomeSchema ):

### another/file.py
from foo.bar.schema import SomeSchema

# do something with SomeSchema:
smth = SomeSchema()
smth.fcnt()

(還要注意,模塊名稱應按照PEP8的建議使用小寫字母,並且只有類名稱才能使用PascalCase

順便說一下,這不僅適用於Python,還適用於一般編程。 有一些語言(例如Java和C#)要求在類內部將函數聲明為靜態語言,因為出於某些奇怪的原因,它們不允許在類外部編寫代碼,但是即使這些語言也具有用於構造代碼的模塊/適當的命名空間。 也就是說,通常不將課程放到其他課程中(有時會放進去,但出於與您完全不同的原因/目標)。

因此,基本上“類”是指“類型”或“具有相似行為的一組對象”; 一旦您忽略了該原則/定義,就將按定義編寫錯誤的代碼。

PS。 如果您使用的是Python 2.x,則應該從object繼承您的類,以獲得新樣式的類。

PPS。 在任何情況下,即使從技術上來講,您要執行的操作也無法在Python中正常工作:

class fake_namespace:
    def some_function():
        pass
    class RealClass:
        some_function  # <-- that name is not even visibile here;
                       # you'd have to use fake_namespace.some_function instead

...這就是我報告我得到異常的原因:NameError:未定義名稱'some_function'。

根據您的編輯進行編輯:

我不太確定為什么要這么復雜。 也有一些陳述是錯誤的:

如果我要使用:import foo.bar.schema,那么我必須像x = foo.bar.schema.User那樣使用它?

否。請了解Python模塊的工作方式。

我想在Schema名稱空間中有一個名為User的類,在Model名稱空間中有一個名為User的類。 我不是嗎 也許我應該使用前綴? 類似於SchemaUser類和ModelUser類

請注意,名稱空間aka模塊應為lowercase而不是PascalCase

如果我有很多的話,那我就想通過拆分SomeXSchema來消除無法讀取的故障-每個文件一個。 我可以以某種方式完成此操作嗎?

是; 您可以將您的類放在單獨的子模塊中,例如schema1/class1.pyschema/class2.py等; 那么您可以將它們“收集”到schema/__init__.py以便可以直接從schema導入它們:

# schema/__init__.py
from .class1 import Class1
from .class2 import Class2

__all__ = [Class1, Class2]  # optional

一般說明:您可以使用不同的方式命名模式模塊,例如schema1schema2等; 那么您可以像這樣使用它們:

from somewhere import schema1
from somewhere_else import schema2

s1_user = schema1.User()
s2_user = schema2.User()
# etc

有關Python模塊如何工作的更多信息,請參見http://docs.python.org/2/tutorial/modules.html

名稱和綁定

您可以閱讀Python naming and binding並了解Python名稱空間的工作方式。

范圍定義了塊中名稱的可見性。 如果在塊中定義了局部變量,則其范圍將包括該塊。 如果定義發生在功能塊中,則范圍將擴展到定義塊中包含的任何塊,除非所包含的塊為名稱引入了不同的綁定。 The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods this includes generator expressions since they are implemented using a function scope.

順便說一句,使用globals()locals()可以幫助調試變量綁定。

用戶問題

您可以嘗試以下方法:

from model import User as modelUser
from foo.bar.schema import User as schemaUser

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM