如何使用元类在Python中生成属性? 我有一些数据记录,其中的字段之间有一些关系。 我希望将每个记录作为类型(类)并自动生成这些属性和关系。
我想将此关系指定为数据结构(例如字典)并自动生成具有属性的类
Record 1
Field description
----------------------------
numOfPin no# of following pin array
pin_array array with numOfpin elements
read_result if opt_flag bit 0 is set, invalid. ignore this value
opt_flag ...
Record 2
....
编辑:澄清.. 缺失/无效字段和可选标志的属性逻辑对于所有记录都是相同的。所以我想在元类中抽象它。
例如伪Python代码:
record1_spec = { 'numOfpin', ('pin_array','numOfPin'),
'opt_flag', ('read_result','opt_flag') }
record2_spec = { 'numOfsite', ('site_array','numOfsite'),
'opt_flag', ('test_result','opt_flag') }
class MetaClass:
getter_generator( ele, opt ):
if opt : return ele
else return None
get class name (eg. record1) then fetch record_spec to create class
for ele in record_spec:
if ele is tuple type: # relation between field
class.attribute[ele[0]] = getter_generator(ele[0], ele[1])
class record1(metaclass = Metaclass):
...
然后 record1
类将具有 record1_spec
中定义的所有属性。
逻辑是,如果设置了某个选项字段,则某些属性会返回适当的值。
最佳答案
好吧,让我们看看兔子洞有多深......
您似乎需要做两件事。一种是动态创建属性,另一种是添加它们。首先让我们看看属性的创建,这非常简单 - 通过在函数定义之前放置 @property
来创建属性,或者按照装饰器的行为来创建 - 调用 property
以函数作为参数。因此,我们动态创建一个函数,并对其调用 property
,很简单:
def make_property(params):
def fn(self):
return use_self_and_params_to_calculate_result(self, params)
return property(fn)
例如 params
可以是一个字段名称,然后您可以通过在内部执行 return getattr(self, fieldname)
返回它(即 fn
)函数。
现在进入下一部分,创建类。类创建中的 metaclass
参数仅直接用于此目的 - 它不必是实际的元类,它只是被调用并且应该返回被视为类的东西。正常的用例虽然是让 metaclass
参数作为类的类型,但在这种情况下我们实际上不需要它:
def meta(name, bases, attrs):
attrs = dict(attrs)
attrs["x"] = make_property("_x")
return type(name, bases, attrs)
class record1(metaclass=meta):
pass
现在我们可以通过globals()
在meta
中查找record1_spec
(meta
) > 是用 "record1"
作为第一个参数调用的),但这有什么乐趣呢。让我们更深入地挖掘这个兔子洞,meta
只是用您在基类所在的位置放置的任何内容来调用 - 它恰好是 type
希望它们是类,但我们不需要这样做,我们只需要在调用 type
时确保这是真的:
def meta(name, bases, attrs):
record_spec = bases[0]
bases = bases[1:]
attrs = dict(attrs)
examine_record_spec_and_populate_attrs(attrs, record_spec)
attrs["spec"] = record_spec
return type(name, bases, attrs)
class record1(['numOfpin', ('pin_array','numOfPin'),
'opt_flag', ('read_result','opt_flag')], metaclass=meta):
pass
如果您需要的话,您可以找到 record1.spec
的规范。如果您的记录规范采用键值对形式(即像dict
),您甚至可以在类定义中使用关键字参数:
def meta(name, bases, attrs, **spec):
attrs = dict(attrs)
examine_record_spec_and_populate_attrs(attrs, spec)
attrs["spec"] = spec
return type(name, bases, attrs)
class record1(numOfpin = ('pin_array','numOfPin'),
opt_flag = ('read_result','opt_flag'), metaclass=meta):
pass
关于python - 如何在元类中自动生成属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31937158/