2010-04-06 3 views
10

Мне нужно динамически создавать атрибуты класса из словаря DEFAULTS.Динамически создавать атрибуты класса

defaults = { 
    'default_value1':True, 
    'default_value2':True, 
    'default_value3':True, 
} 

class Settings(object): 
    default_value1 = some_complex_init_function(defaults[default_value1], ...) 
    default_value2 = some_complex_init_function(defaults[default_value2], ...) 
    default_value3 = some_complex_init_function(defaults[default_value3], ...) 

Я мог бы также добиться этого, имея sth. например, __init__ для создания классов, чтобы динамически создавать эти атрибуты из словаря и сохранять много кода и глупо работать.

Как вы это сделаете?

спасибо, что заблаговременно!

ответ

3

Я думаю, что это дело для метакласса:

class SettingsMeta(type): 
    def __new__(cls, name, bases, dct): 
     for name, value in defaults.items(): 
      dct[name] = some_complex_init_function(value, ...) 
     return type.__new__(cls, name, bases, dct) 

class Settings(object): 
    __metaclass__ = SettingsMeta 
+2

как мы проходим по умолчанию, или как мы можем инициализировать любой объект этого класса Настройки –

+1

же вопрос с @vijayshanker – TomSawyer

+0

Код зависит от 'defaults' словаря быть в при определении класса «Настройки». –

19

Вы могли бы сделать это без метаклассами с помощью декораторов. Таким образом, это немного более ясно IMO:

def apply_defaults(cls): 
    defaults = { 
     'default_value1':True, 
     'default_value2':True, 
     'default_value3':True, 
    } 
    for name, value in defaults.items(): 
     setattr(cls, name, some_complex_init_function(value, ...)) 
    return cls 

@apply_defaults 
class Settings(object): 
    pass 

До Python 2.6 класса декораторов были недоступны. Таким образом, вы можете написать:

class Settings(object): 
    pass 
Settings = apply_defaults(Settings) 

в старых версиях python.

В указанном примере apply_defaults многоразов ... Ну, за исключением того, что по умолчанию жестко закодированы в теле декоратора :) Если у вас есть только один случай, вы даже можете упростить код для этого:

defaults = { 
    'default_value1':True, 
    'default_value2':True, 
    'default_value3':True, 
} 

class Settings(object): 
    """Your implementation goes here as usual""" 

for name, value in defaults.items(): 
    setattr(Settings, name, some_complex_init_function(value, ...)) 

Это возможно, так как классы (в смысле типов) сами являются объектами в Python.

+1

Вам также нужно вернуть «украшенный» класс ('cls' в первом примере) в конце функции декоратора, не так ли? Понадобился время, чтобы понять, но если я не сделаю этого, класс будет равен «Нет» после определения. Я что-то упускаю, например, например, каким-то образом поставляю класс по ссылке? – Simon

+0

Элегантный способ. – zoujyjs

+0

Как передать значения по умолчанию в файл, подобный этому? A = Настройки (по умолчанию) '' settings.py' - это конкретный файл – TomSawyer

0

При определении класса локальное пространство имен будет преобразовано в пространство имен классов по завершении тела класса. Таким образом, вы можете сделать это с:

class Settings(object): 
    for key, val in defaults.iteritems(): 
     locals()[key] = some_complex_init_function(val, ...) 
+1

-1 [документация] (http://docs.python.org/library/functions. html? highlight = locals # locals) для 'locals()' говорит, что содержимое возвращаемого слова не должно быть изменено. – martineau

+0

Это умно. Благодарю. –

Смежные вопросы