我们的项目从一堆不同的来源收集关于一个对象的大量信息,并且为了审计和解决我们的数据源之间的冲突,我们需要保留一堆关于每个属性的元数据
age = 21
age_metadata = {
'source' : 'office gossip',
'relability' : 0
{
问题是类开始看起来像这样。
class Person
def __init__(self, id, ):
self.id = id
self.id_meta = None
self.age = None
self.age_meta = None
self.name = None
看起来很难看,并且所有属性的数量加倍,所以我想要的是在每个属性下嵌套元数据。因此,如果我需要它,我可以拨打bob.age.meta
而不是bob.age_meta
,我希望这样做,同时保持属性或多或少不变。所以我想要一些总能让我使用它的东西:
def main():
bob = Person(1)
bob.age.meta = 'random metadata'
bob.age = 30
assert bob.age.meta == 'random metadata'
现在我认为应该可以使用描述符类的组合来拦截赋值+一些猴子修补/元分类魔术来保存元数据..但我是所有这些功能的新手并且很容易迷失。这是我当前的草图。从工作代码的方式:
class AttributeWithMeta(object):
"""interceot attribute fucntions"""
def __get__(self, instance, owner):
return self._value
def __set__(self, instance, value):
"""take attribute and somehow replace it with monkey patched version"""
self._value = magic(value,meta)
@staticmethod
def magic(value, meta):
"""adds meta attribute to objects regardless of type"""
return value_with_meta
class Person(object):
age = AttributeWithMeta()
def __init__(self, id):
self.id = id
我是朝着正确的方向前进的吗?有没有其他方法可以做到这一点,我错过了?我想在这里做不可能吗?
如果属性有问题,P.S最坏情况age.get_meta()
是可以接受的。
答案 0 :(得分:1)
bob.age.meta
^ ^
| |_______ This lookup can be managed by type(bob.age) class
|
|___________ This lookup can be managed by type(bob) class, i.e. Person
.meta
的属性访问完全由bob.age
对象处理,因此您的Person
类在这里没有发言权。
通过在Person
类上定义描述符,您可以控制设置/获取/删除age
属性在Person
实例上的行为方式。你在个人实例和属性之间own the dot,可以做任何你想要的事情。但是这种力量并没有达到第二个点 - 即.
和age
之间的meta
。
如果您希望bob.age
从字面上返回整数30,那么您将很难让bob.age.meta
做任何事情而不是提升AttributeError
。那是因为你现在需要在int
类上定义一个描述符,并且在python中不可能使用猴子修补内置类型。无论如何,并非没有terrible and unreliable hacks。
如果您对bob.age
返回对象的某种容器和关联的元数据感到高兴,那么Person
类的描述符可能是您想要的。但是如果你希望bob.age
只返回对象,而bob.age.meta
只返回元数据,那么我认为你正在咆哮错误的树。
一个不那么复杂的设计是每个Person
实例直接有一个meta
dict,这样你就可以查找例如bob.meta['age']
来获取与bob {{1}相关的元数据。 1}}属性。