2013-04-28 189 views
0

我有一組類,它們代表不同的「工具」,每個工具都有一個ID鍵,一個描述,一個標題和一些其他常量。這些都是從「GenericTool」類中分類的。在導入時在Python中註冊對象成員

我想有一種方法來填充字典,鍵入所有子類的ID,以便我可以輕鬆地查找常量,給定ID,但不必維護中央字典。

例如,文件tools/toola.py

import generic_tool as GT 
class ToolA(GT.GenericTool): 

    title = "Tool A" 
    id = "tool_a" 

文件tools/toolb.py

import generic_tool as GT 
class ToolB(GT.GenericTool): 

    title = "Tool B" 
    id = "tool_b" 

我想用這樣的字典落得:

{ 'tool_a': {'title': 'Tool A'}, 
    'tool_b': {'title': 'Tool B'} } 

我已經看過用元類,以及超類__init__()中的代碼,但是th似乎會影響類的運行時創建,而我只關心一次,即第一次導入模塊時。

+0

「*但不必維護中央字典。*」:爲什麼? – Blender 2013-04-28 22:25:14

+0

因爲在課堂上有類特定的信息似乎更加簡潔,而不必照顧完全解耦的列表,這可能很容易失去同步。對於一些課程,當然可以手工完成,但是數百或更多的課程並不能很好地進行擴展,我可以設想一些有點像裝飾器,這些信息是自動收集的。 – Inductiveload 2013-04-28 22:29:45

回答

1

在假設 「而無需維護中央辭典」 的真正含義「沒有哈維持手動更新的字典「解決方案將通過使用元類。這將需要的generic_tool.GenericTool的定義是這樣的:

class GenericToolMeta(type): 
    """Meta classs that is used by Tools to register in a central dictionary.""" 
    tools = {} 

    def __new__(meta, classname, bases, classDict): 
     new_class = type.__new__(meta, classname, bases, classDict) 

     try: 
      meta.tools[new_class.id] = new_class.title 
     except AttributeError: 
      pass 
     return new_class 

class GenericTool(object): 
    __metaclass__ = GenericToolMeta 

當你的基地(GenericTool)使用__metaclass__聲明或直接在你的派生Tools類本身都會自動在定義(註冊即進口時間你叫它):

$ python 
Python 2.7.3 (default, Jan 2 2013, 13:56:14) 
[GCC 4.7.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import generic_tool 
>>> generic_tool.GenericToolMeta.tools 
{} 
>>> import toola 
>>> generic_tool.GenericToolMeta.tools 
{'tool_a': 'Tool A'} 
>>> import toolb 
>>> generic_tool.GenericToolMeta.tools 
{'tool_a': 'Tool A', 'tool_b': 'Tool B'} 
>>> 
+0

是的,我的意思是「手動維護」,這似乎造成了一些混淆。顯然,當__new__被調用時,我也完全誤解了。感謝一個非常明確的例子! – Inductiveload 2013-04-28 22:51:44

1

元類:

class GenericToolMeta(type): 
    tool_dict = {} 

    def __init__(cls, name, bases, dct): 
     tool_dict[cls.id] = {'title': cls.title} 
     super(GenericToolMeta, cls).__init__(name, bases, dct) 
import generic_tool as GT 
class ToolB(GT.GenericTool, metaclass=GT.GenericToolMeta): 
    title = "Tool B" 
    id = "tool_b" 

或者與裝飾:

tool_list = [] 

def tool(title, id): 
    def decorator(cls): 
     cls.title = title 
     cls.id = id 
     tool_list[id] = title 
     return cls 

    return decorator 
import generic_tool as GT 

@GT.tool(id="tool_b", title="Tool B") 
class ToolB(GT.GenericTool): 
    # ...