在导入时在Python中注册对象成员
问题描述:
我有一组类,它们代表不同的“工具”,每个工具都有一个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似乎会影响类的运行时创建,而我只关心一次,即第一次导入模块时。
答
在假设 “而无需维护*辞典” 的真正含义“没有哈维持手动更新的字典“解决方案将通过使用元类。这将需要的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
答
元类:
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):
# ...
“*但不必维护*字典。*”:为什么? – Blender 2013-04-28 22:25:14
因为在课堂上有类特定的信息似乎更加简洁,而不必照顾完全解耦的列表,这可能很容易失去同步。对于一些课程,当然可以手工完成,但是数百或更多的课程并不能很好地进行扩展,我可以设想一些有点像装饰器,这些信息是自动收集的。 – Inductiveload 2013-04-28 22:29:45