如何在Python中实现类/对象元数据?
我正在开发一个结构化数据分析框架,这个框架是基于节点之间的流数据进行工作的。现在,节点是作为框架提供的根节点类的子类来实现的。对于每个节点类或工厂,我需要一些元数据,比如节点的属性列表、它们的描述和节点的输出。这些元数据可能是给最终用户在前端应用中使用的,也可能是给程序员使用的,比如一些其他的流管理工具。将来还会有更多这样的工具。
(注意,我在写这段代码的时候刚开始学习Python)
目前,元数据是通过一个类变量来提供的。
class AggregateNode(base.Node):
"""Aggregate"""
__node_info__ = {
"label" : "Aggregate Node",
"description" : "Aggregate values grouping by key fields.",
"output" : "Key fields followed by aggregations for each aggregated field. Last field is "
"record count.",
"attributes" : [
{
"name": "keys",
"description": "List of fields according to which records are grouped"
},
{
"name": "record_count_field",
"description": "Name of a field where record count will be stored. "
"Default is `record_count`"
}
]
}
更多示例可以在这里找到。
我觉得可以用更简洁的方式来实现。这里有一个限制:因为节点是自定义的子类,所以应该尽量减少与未来可能出现的属性名称的冲突。
我在想的是把现在的node_info拆分开来。它本来是打算私有化给框架使用的,但现在我意识到它的用途更广泛。我在考虑使用节点属性:这样可以有一个公共的属性命名空间,不会占用太多可能的自定义节点属性的名称。
我的问题是:在Python程序中,提供这种元数据的最常见方式是什么?用一个包含字典的单一变量?每个元数据属性用多个变量?(这样会与限制冲突)自定义类/结构?使用某种前缀,比如node_*,然后用多个变量?
3 个回答
0
在Python类中,唯一能够修改类定义本身(也就是元数据)的元素是__new__()
这个函数。这个函数在对象真正被创建之前就会被调用,也就是在对象初始化之前。你可以利用这个函数在对象用__init__()
进行初始化之前,读取或修改你的类或节点的内部结构。
1
你所描述的很多功能其实和epydoc有很多相似之处:
>>> class AggregateNode(base.Node):
... r"""
... Aggregate values grouping by key fields.
...
... @ivar keys: List of fields according to which records are grouped
...
... @ivar record_count_field: Name of a field where record count will be
... stored.
... """
... record_count_field = "record_count"
...
... def get_output(self):
... r"""
... @return: Key fields followed by aggregations for each aggregated field.
... Last field is record count.
... """
...
>>> import epydoc.docbuilder
>>> api = epydoc.docbuilder.build_doc(AggregateNode)
>>> api.variables['keys'].descr.to_plaintext(None)
u'List of fields according to which records are grouped\n\n'
>>> api.variables['record_count_field'].value.pyval
'record_count'
1
我不太确定在Python对象中存储自定义元数据是否有什么“标准”的方法,但举个例子,Python的dbus实现会在发布的方法和信号前加上一个"_dbus
"的前缀。