2010-04-06 7 views
10

Potrzebuję dynamicznie tworzyć atrybuty klas ze słownika DEFAULTS.Dynamicznie twórz atrybuty klas

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], ...) 

Mogę to osiągnąć również dzięki temu. jak __init__ do tworzenia klas, aby dynamicznie tworzyć te atrybuty ze słownika i zapisywać dużo kodu i głupią pracę.

Jak to zrobić?

Dziękuję bardzo z góry!

Odpowiedz

3

myślę, że to sprawa dla metaklasą:

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

w jaki sposób przekazać domyślne, lub w jaki sposób możemy zainicjować każdy obiekt tego Ustawienia Klasa –

+1

samo pytanie z @vijayshanker – TomSawyer

+0

Kod zależy od 'defaults' będąc w słowniku zakres przy definiowaniu klasy "Ustawienia". –

19

Można to zrobić bez metaclasses korzystających dekoratorów. W ten sposób jest nieco bardziej przejrzyste 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 

Przed dekoratorów klasy Python 2.6 były niedostępne. Możesz więc napisać:

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

w starszych wersjach Pythona.

W podanym przykładzie apply_defaults jest wielokrotnego użytku ... No, chyba, że ​​domyślnie są zakodowane w ciele dekoratora za :) Jeśli masz tylko jedną sprawę można jeszcze uprościć swój kod do tego:

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, ...)) 

Jest to możliwe, ponieważ klasy (w sensie typów) są obiektami w Pythonie.

+1

Musisz również zwrócić "dekorowaną" klasę ("cls" w pierwszym przykładzie) na końcu funkcji dekoratora, nieprawdaż? Zajęło mi to trochę czasu, ale jeśli tego nie zrobię, klasa po definicji będzie równała się "Brak". Czy brakuje mi czegoś, jak na przykład jakiś sposób dostarczenia klasy przez odniesienie? – Simon

+0

Elegancki sposób. – zoujyjs

+0

W jaki sposób przekazuję wartości domyślne do pliku takiego jak ten 'a = Ustawienia (domyślne)' 'settings.py' to konkretny plik – TomSawyer

0

Podczas definiowania klasy lokalny obszar nazw zostanie przekonwertowany na przestrzeń nazw klasy na zakończenie treści klasy. Jako takie, można to osiągnąć z:

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

-1 The [documentation] (http://docs.python.org/library/functions. html? highlight = locals # locals) dla 'locals()' mówi, że zawartość zwróconego słownika nie powinna być modyfikowana. – martineau

+0

To jest sprytne. Dzięki. –

Powiązane problemy