Создание динамического поля класса перед механизмом метакласса - PullRequest
2 голосов
/ 06 августа 2010

Я пытаюсь избавиться от 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 ]

2 голосов
/ 06 августа 2010
>>> values = 'one', 'two', 'three'
>>> A = type('A', (object,), {i: i + ' value' for i in values})
>>> A.one
'one value'
>>> A.three
'three value'
2 голосов
/ 06 августа 2010

Я бы просто унаследовал от метакласса и сделал бы там

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 голосов
/ 06 августа 2010

Использование функция setattr .

class A(object):
  pass

for field in ['one', 'two', 'three']:
  setattr(A, field, field + ' value')
1 голос
/ 06 августа 2010

Это тоже работает, и я думаю, что это счастливый конец ...

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/

1 голос
/ 06 августа 2010

Вы говорите, что хотите динамически генерировать что-то, что может обработать метакласс.Есть очень простой способ добиться этого, не прибегая к таким хакерским действиям, как exec.Все, что вам нужно сделать, это подумать об этом по-другому: изменить метакласс так, чтобы там генерировались имена.

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'
>>> 

, и если вы не хотите изменять существующий метакласс, вы можете создать его подкласс.

0 голосов
/ 06 августа 2010

Позвольте мне предвосхитить это, сказав, что это невероятно хакерский, но исключает exec.Мы просто вставляем атрибуты в текущий фрейм стека, когда выполняется код в операторе класса.Гарантируется, что он работает только на CPython, и в руководстве есть предупреждения против этого.Я настоятельно рекомендую вам воспользоваться метаклассом duncans.

import sys

class A(object):
    for field in ['one', 'two', 'three']:
        sys._getframe().f_locals[field] = field + ' value'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...