在元类机器之前创建动态类字段

时间:2010-08-06 11:35:48

标签: python dynamic

我试图在类似的代码中删除exec

class A(object):
    for field in ['one', 'two', 'three']:
        exec '%s = "%s value"' % (field, field)

......所以:

>>> A.one
'one value'
>>> A.two
'two value'
>>> A.three
'three value'

编辑:并且在实例化A.one之前满足主题中提到的要求,即'one value'A(不要误认为A()实例化)。

有办法吗?

6 个答案:

答案 0 :(得分:2)

使用the setattr function

class A(object):
  pass

for field in ['one', 'two', 'three']:
  setattr(A, field, field + ' value')

答案 1 :(得分:2)

我只是继承了元类并在那里做了

class MyMetaClass(MetaClass):
    def __new__(meta, classname, baseclasses, classdict):
        fields = classdict['__myfields__']
        for field in fields:
            classdict[field] = field + ' value'
        del classDict['__myfields__']
        MetaClass.__new__(meta, classname, baseclasses, classdict)

然后你可以这样做:

class A(object):
    __metaclass__ = MyMetaClass
    __myfields__ = ['one', 'two', 'three']

答案 2 :(得分:2)

>>> values = 'one', 'two', 'three'
>>> A = type('A', (object,), {i: i + ' value' for i in values})
>>> A.one
'one value'
>>> A.three
'three value'

答案 3 :(得分:1)

您说您希望动态生成元类可以处理的内容。有一种非常简单的方法可以实现这一目标,而不需要像exec那样使用hackery。您所要做的就是以不同的方式考虑这一点:修改元类,以便在那里生成名称。

class AutoFieldMeta(type):
    def __new__(mcs, name, bases, d):
        for field in d.get('AUTOFIELDS', ()):
            d[field] = field + ' value'
        return type.__new__(mcs, name, bases, d)

class A(object, metaclass=AutoFieldMeta):
    AUTOFIELDS = ('one', 'two', 'three')

>>> A.one
'one value'
>>> 

如果您不想修改现有的元类,则可以将其子类化。

答案 4 :(得分:1)

这也有效,我认为这是一个快乐的结局......

class A(object):
    for a in ['one', 'two', 'three']:
        locals().update({a: a + ' value'})

对于在Python中搜索赋值表达式的任何人来说,这与aaronasterling答案的情绪相同:):

http://code.activestate.com/recipes/202234-assignment-in-expression/

答案 5 :(得分:0)

让我先说明这是非常的hackish但是消除了执行官。我们只是在执行类语句中的代码时将属性粘贴在当前堆栈帧上。它只能保证在CPython上工作,并且在手册中有警告不要这样做。我强烈建议您使用duncans元类解决方案。

import sys

class A(object):
    for field in ['one', 'two', 'three']:
        sys._getframe().f_locals[field] = field + ' value'