[英]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中使用,對吧?)。
感謝您提前答復。
編輯:好的,我已經做了一些測試(我認為我已經完成了,但是看起來還沒有..)。
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所說的-類不是名稱空間。 得到它了! 在我的第一個代碼段中,是的,我應該使用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
回到包格式。 有了這個:
### another/file.py from foo.bar.schema import SomeSchema # do something with SomeSchema: smth = SomeSchema() smth.fcnt()
我必須創建一個模塊foo/bar/schema.py
在其中必須放置所有SomeXSchema
類。 如果我有很多的話,那我就想通過拆分SomeXSchema來消除無法讀取的故障-每個文件一個。 我可以以某種方式完成此操作嗎? 我想例如稱此類: User
。 這就是事情。 也許我做錯了嗎? 我想有一個名為類User
在schema
命名空間和命名的類User
在model
的命名空間 。 我不是嗎 也許我應該使用前綴? 像class SchemaUser
class ModelUser
和class 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嗎?
如果有人認為應該更改主題,請繼續,給我一些更有意義的信息,我將不勝感激。
您正在通過嘗試做自己想做的事情向上游游泳。
類用於定義新的數據類型,而不是將代碼的相關部分組合在一起的一種手段。 模塊非常適合於此,由於問題標題中的“(相對於正確的包裝結構)”部分,我想您知道的很好。
模塊也可以作為對象導入,因此可以實現所需的功能:
### 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.py
, schema/class2.py
等; 那么您可以將它們“收集”到schema/__init__.py
以便可以直接從schema
導入它們:
# schema/__init__.py
from .class1 import Class1
from .class2 import Class2
__all__ = [Class1, Class2] # optional
一般說明:您可以使用不同的方式命名模式模塊,例如schema1
, schema2
等; 那么您可以像這樣使用它們:
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.