programattically定义的类定义属性

问题描述:

我有一个为应用程序保持不变数据库值对象,它看起来像某事,这一小撮:programattically定义的类定义属性

class TestObject(object): 
    """reflects constants in _test_object""" 
    _pairs = (
     (1  , 'A'),   
     (2  , 'B'),   
     (4  , 'C'),   
     (8  , 'D'),   
    ) 
    mapping = setup(_pairs) 

mapping函数创建一个字典,让我的AK,v和v,k查找基于_pairs。它们都以“id,name”的形式出现。

为了使事情的应用程序更容易,我经常设置“文本值”作为一个属性,以及:

class TestObject(object): 
    ... 
    ... 
    A = 1 
    B = 2 
    C = 4 
    D = 8 

虽然这使得使用类的真的很棒,这是一个有点笨拙到重新输入这一切,并保持同步。另外,我必须编写单元测试以确保属性与_pairs中的正确ID匹配。

我一直试图围绕一种方式来包装我的头,以避免写出来,并自动填充每个TestObject类与应用程序启动时的属性。

我知道我可以覆盖这个类并让它检查_pairs/mapping attibute以进行故障转移,但是我真的很感兴趣,是否有可能根据需要将程序填充到类中。目前还没有__class__,因为该类还没有定义。

仅仅是明确的,我想要做的东西的种类是沿此线:

class NotValidPython(): 
    _pairs = ((1,'A'),) 
    for (k,v) in _pairs: 
     setattr(__class__, v, k) 

使用装饰:

def dynamic_attrs(cls): 
    for v, k in getattr(cls, '_pairs', []): 
     setattr(cls, k, v) 
    # you also optionally delete the _pairs attr here using del cls._pairs 
    return cls 

@dynamic_attrs 
class TestObject(object): 
    """reflects constants in _test_object""" 
    _pairs = (
     (1  , 'A'), 
     (2  , 'B'), 
     (4  , 'C'), 
     (8  , 'D'), 
    ) 
+0

哇。辉煌!非常感谢。 –

一个元可以用于此目的。您可以覆盖元类中的__new__,然后填充属性字典或覆盖__init__,然后覆盖属性字典或使用setattr设置类对象本身的属性。

使用__new__

class Meta(type): 

    def __new__(meta, clsname, bases, dct): 
     dct.update(dict((k, v) for v, k in dct.pop('_pairs'))) 
     return type.__new__(meta, clsname, bases, dct) 

class TestObject(object): 
    __metaclass__ = Meta 

    """reflects constants in _test_object""" 
    _pairs = (
     (1  , 'A'),   
     (2  , 'B'),   
     (4  , 'C'),   
     (8  , 'D'),   
    ) 

使用__init__

class Meta(type): 

    def __init__(cls, clsname, bases, dct): 
     attrs = dct.pop('_pairs') 
     for v, k in attrs: 
      setattr(cls, k, v) 
+0

因此,这是辉煌的,但它无法正常工作 - 是为了我的需要。如果我有'AnotherTestObject',其值((1,'F'),(2,'G'),...)所有数据都在元类的字典中,所以碰撞和属性是不是普通班的本地人。 –

+0

@JonathanVanasco对不起,我不明白你在这里意味着什么,碰撞是什么意思? –

+0

看看这个要点 - https://gist.github.com/jvanasco/9141157说明命名空间冲突。因为K/V存储在元类而不是类中,所以你只能对一个类使用'Meta'。如果另一个使用'Meta'的类具有'A'值,它将覆盖所有先前的'A'值;如果另一个类提供'Z'值,它将使'Z'对所有其他类可用。 –

无需使用元类。只要把你的代码相同的模块作为类定义,但类定义:

class TestClass(): 
    _pairs = ((1,'A'),) 

for (k, v) in TestClass._pairs: 
    setattr(TestClass, v, k) 
+0

这种方法的问题是我需要识别所有适用的类;这就是为什么我想将它整合到类定义中。 –

+0

在这种情况下,我可能会用@ F.J的答案。 – bdesham