2012-03-04 48 views
3

不知道是否有一個乾淨的方式來處理它,它只是在視覺上將每個對象/類放置到它自己的模塊下通用包中。從包中的任意模塊直接訪問類

例如:

  • /設置/
  • /設置/ __init__.py
  • /設置/ AbstractSetting.py
  • /設置/ Float.py
  • /設置/ String.py

每個模塊內每個類具有相同的名稱作爲模塊,並在那一刻我一直這樣做:

import Settings 
mysetting = Settings.Float.Float() 

..這是給我的這種雙重「浮動」的名字。

我可以做,在封裝的__init__.py

from Float import Float 

..所以,我可以再做:

import Settings 
mysetting = Settings.Float() 

,但我想這個包是動態地更新到無論我放在裏面的模塊。因此,第二天,當我將「Knob.py」添加到此包中時,我可以這樣做:

import Settings 
myknob = Settings.Knob() 

有意義嗎?

但是,我之前沒有使用過包裝,仍然試圖圍繞它包裝並儘量讓它變得簡單。此時,我發現將所有類放在一個大型主模塊中變得越來越麻煩。

也許包是不是要走的路?我有什麼替代方案?

非常感謝。

編輯:我想這樣做的主要原因是讓用戶編寫自己的模塊,將與應用程序的其餘部分集成。一個本地的「插件」結構,如果你願意的話。

每個模塊將包含一個由具有默認值的超類繼承的類。然後,該應用程序擁有一個帶有可用模塊的瀏覽器,點擊該模塊可以顯示模塊屬性下的相關信息。然後包含的每個類都有一個類似的應用程序可以使用的界面。

我做了一些進一步的閱讀,顯然這不是要走的路。我很想聽聽你的想法,但是這種方法的好處和壞處是什麼。

回答

2

有很多插件系統。它通過一個這樣的系統yapsy(又一個插件系統)的名稱來例證。

您可以創建一個對象,它提供必要的接口:

class Settings(object): 
    def __getattr__(self, attr): 
     return load_plugin(attr) 

settings = Settings() 

在您的代碼:

from settings import settings 

knob = settings.Knob() 

你可以使用任何你喜歡的實施load_plugin()例如,從問題的代碼:

from importlib import import_module 

def load_plugin(name): 
    m = import_module('Settings.'+name) 
    return getattr(m, name) 
+0

+1看起來很***「Pythonic」,就像簡單,靈活和可擴展一樣。 – martineau 2012-03-04 21:59:10

+0

這似乎是要走的路。這個應用程序的關鍵(它本質上只是批量處理一堆用戶創建的Python模塊)很簡單,我打算在插件編寫不正確的情況下實施回退。 (在這種情況下,只需導入插件並放棄或輕輕打印可能返回的任何異常) – 2012-03-06 12:17:37

+0

經過一些進一步測試:喜歡它。完美的作品。謝謝! – 2012-03-09 19:41:59

3

你應該知道,這不是Python的方式。 「每個文件一個類」是Java哲學,不適用於Python世界。我們通常將模塊名稱命名爲小寫,並將相關的類放在同一個文件中(在您的示例中,所有類都將進入settings.py或者從那裏明確導入)。但我想你希望用戶提供插件的事實是你的方法的合法理由(immdbg以同樣的方式做,我認爲)。

所以,如果你真的想這樣做,你可以把這樣的事情到您的Settings/__init__.py

import os 
import glob 
import imp 

for f in glob.glob(os.path.join(os.path.dirname(__file__), '*.py')): 
    modname = os.path.basename(f)[:-3] 
    if modname.startswith('__'): continue 
    mod = imp.load_source(modname, f) 

    globals()[modname] = getattr(mod, modname) 

    # or if you just want to import everything (even worse): 
    #for name in dir(mod): 
    # if name.startswith('__'): continue 
    # globals()[name] = getattr(mod, name) 

你能感覺到怎樣的Python開發者不希望你這樣做嗎? :)

+0

恕我直言,像這樣的東西是一種合理的方式來實現一個dyn amic「插件」模塊架構。 – martineau 2012-03-04 19:57:46

+0

我完全認爲它是非常規的,當我第一次嘗試時,它確實感覺有點不對勁。 :)謝謝你讓我知道,我會小心的給這種方法。 – 2012-03-06 12:14:39

+0

FWIW,這可以擴展到允許在模塊內部使用稍微更精細的代碼在'__init __。py'文件中輸入任意東西,參見[這個答案](http://stackoverflow.com/questions/14426574/how-to-import-members-of-modules-in-a-package/14428820#14428820)到另一個問題。 – martineau 2014-03-01 15:59:09