2010-03-29 7 views
14

Gibt es eine Möglichkeit, dass ich __init__ definieren kann, so dass Schlüsselwörter definiert in **kwargs der Klasse zugeordnet sind?Wie kopiere ich ** kwargs zu sich selbst?

Zum Beispiel, wenn ich eine ValidationRule Klasse mit ValidationRule(other='email') initialisiert wurde, soll der Wert für self.other die Klasse hinzugefügt werden, ohne explizit mit jedem möglichen kwarg zu nennen.

class ValidationRule: 
    def __init__(self, **kwargs): 
     # code to assign **kwargs to .self 
+0

Gibt es einen Grund, warum Sie keine neuen Klassen verwenden? –

+0

@Georg: Ich weiß nicht einmal, was neue Klassen sind? Ich verwende Python 2.5, wenn das relevant ist. – mpen

+3

Um eine Newstyle-Klasse zu erstellen, müssen Sie nur von einer Newstyle-Klasse (normalerweise 'object') erben. Verwenden Sie daher' class ValidationRule (object): 'Weitere Informationen finden Sie hier: http://www.python.org/doc/newstyle/ –

Antwort

10

Dies kann nicht der sauberste Weg sein, aber es funktioniert:

class ValidationRule: 
    def __init__(self, **kwargs): 
     self.__dict__.update(kwargs) 

Ich glaube, ich ony's solution bevorzugen, weil es verfügbar Eigenschaften schränkt Sie aus der Patsche zu halten, wenn Sie Ihre Eingabe aus anderen Quellen kommt.

+0

Es wird nicht korrekt funktionieren, wenn Variable eine "magische" ist. Betrachte [Propertyes] (http://docs.python.org/2/library/functions.html#property) und [slotted objects] (http://docs.python.org/2/reference/datamodel.html?highlight) = __ Slots __ # Slots). Das gilt für Python 2 und Python 3. – WGH

11

Man könnte so etwas tun:

class ValidationRule: 
    def __init__(self, **kwargs): 
     for (k, v) in kwargs.items(): 
     setattr(self, k, v) 
+2

Wenn die Kwargs-Liste lang ist, können Sie * iteritems() * anstelle von * items() * verwenden. Für Ihren Zweck sollte das aber in Ordnung sein. –

+0

@ GeorgSchölly Was ist der Unterschied zwischen 'iteritems()' und 'items()'? –

+0

@StevenVascellaro In Python 2 'iteritems()', gibt einen Generator zurück, während 'items()' eine Liste zurückgibt. In Python 3 gibt 'items()' eine Itemview zurück und 'iteritems()' wurde entfernt. Ich bevorzuge 'items()', weil es mit beiden kompatibel ist. Für sehr große Dicts verwende ich immer noch 'iteritems()'. Siehe auch https: // stackoverflow.com/questions/13998492/iteritems-in-python –

17

Ich denke somewhere on the stackoverflow ich solche Lösung gesehen habe. Auf jeden Fall kann es wie folgt aussehen:

class ValidationRule: 
    __allowed = ("other", "same", "different") 
    def __init__(self, **kwargs): 
     for k, v in kwargs.iteritems(): 
      assert(k in self.__class__.__allowed) 
      setattr(self, k, v) 

Diese Klasse nur in __allowed aufgeführten Argumente mit einer weißen Liste Attributnamen akzeptiert.

+0

ValidationRule ist nur meine Basisklasse, und es hat keine eigenen Attribute, also gibt es nichts, was sie versehentlich überschreiben können, aber ansonsten wäre das ein guter Sicherer Wächter;) Ich würde in diesem Fall wahrscheinlich eine Blacklist anstelle einer Whitelist verwenden, um sie nicht zu sehr einzuschränken. – mpen

3
class ValidationRule: 
    def __init__(self, **kwargs): 
     self.__dict__.update(kwargs) 
1

Sie können Ihre kwargs Argumente festlegen, indem Sie das Attribut __dict__ der Instanz aktualisieren.

class ValidationRule: 
    def __init__(self, **kwargs): 
     self.__dict__.update(kwargs) 
-1

fand ich die oben genannten Antworten hilfreich und dann verfeinert:

class MyObj(object): 
    def __init__(self, key1=1, key2=2, key3=3): 
     for (k, v) in locals().iteritems(): 
      if k != 'self': 
       setattr(self, k, v) 

Test:

>>> myobj = MyObj(key1=0) 
>>> print myobj.key1 
0 

und Validierung auch gibt es:

>>> myobj = MyObj(key4=4) 
TypeError: __init__() got an unexpected keyword argument 'key4' 
1

Dies in Betracht gezogen werden könnte Schöner als das Aktualisieren __dict__:

class C: 
    def __init__(self, **kwargs): 
     vars(self).update(kwargs) 

>>> c = C(a='a', b='b') 
>>> c.a # returns 'a' 
>>> c.b # returns 'b'