我有一些对象包含应用程序的常量数据库值,看起来像这样:
class TestObject(object):
"""reflects constants in _test_object"""
_pairs = (
( 1 , 'A' ),
( 2 , 'B' ),
( 4 , 'C' ),
( 8 , 'D' ),
)
mapping = setup(_pairs)
mapping
函数创建一个dict,根据_pairs
给我一个k,v和v,k查找。它们都是“id,name”的形式。
为了让应用程序更容易,我经常将“文本值”设置为属性:
class TestObject(object):
...
...
A = 1
B = 2
C = 4
D = 8
虽然这使得使用这些类非常棒,但重新键入所有内容并使其保持同步有点笨拙。另外,我必须编写单元测试以确保属性与_pairs中的正确ID匹配。
我一直试图绕过一种方法来跳过这个问题,然后只使用应用程序启动时的属性自动填充每个TestObject类。
我知道我可以覆盖类并让它检查_pairs / mapping属性以进行故障转移,但我真的很感兴趣是否有可能以编程方式填充我需要的类。还没有__class__
,因为该类尚未定义。
为了清楚起见,我想要做的事情的类型是:
class NotValidPython():
_pairs = ((1,'A'),)
for (k,v) in _pairs:
setattr( __class__, v, k )
答案 0 :(得分:3)
使用装饰者:
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' ),
)
答案 1 :(得分:1)
可以使用元类。您可以覆盖元类中的__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)
答案 2 :(得分:0)
无需使用元类。只需将代码放在与类定义相同的模块中,但外部类定义:
class TestClass():
_pairs = ((1,'A'),)
for (k, v) in TestClass._pairs:
setattr(TestClass, v, k)