2017-03-07 7 views
2

ich in Python neu bin. Ich habe ein Objekt mit einigen Feldern und ich habe eine Liste von Feldnamen und Werten, aber alle Werte in dieser Liste sind Zeichenfolgen. Ich muss ein Objektfeld finden und den Wert zuweisen. Ich habe bereits herausgefunden, wie man das Feld findet. Ich habe jedoch ein Problem mit der Typumwandlung.Python: get Art und wandelt diese Art

Zum Beispiel:

class SomeEntity: 

    def __init__(self): 
     self.id = 0 
     self.name = "" 
     self.some_attr = {} 


def applyValues(entity, list_of_values): 
    for key, value in list_of_values: 
     if hasattr(entity, key): 
      setattr(entity, key, value) # !!! here is the problem to convert to type 

Ich brauche so etwas wie diese:

x = getattr(entity, key) 
type_attr = type(x) 
converted = type_attr(value) 
setattr(entity, key, converted) 

Wie kann ich das tun? Oder kann ich etwas anderes benutzen?

+0

Das sieht aus wie ein Duplikat eines der vielen, vielen Fragen, für die die akzeptierte Antwort „ein Wörterbuch verwenden Sie stattdessen“ ist. – tripleee

+0

Ich kippe Wörterbuch statt Klasse verwenden, weil ich diese Klasse von protobuf erzeugt haben – arthas

Antwort

2

Wenn der Wert Strings gültige Python-Literale sind, können Sie ast.literal_eval t verwenden o diese Strings sicher in Python-Objekte auswerten.

import ast 

class SomeEntity: 
    def __init__(self): 
     self.id = 0 
     self.name = "" 
     self.some_attr = {} 

def apply_values(entity, list_of_values): 
    for key, value in list_of_values: 
     if hasattr(entity, key): 
      converted = ast.literal_eval(value) 
      setattr(entity, key, converted) 

entity = SomeEntity() 

attr_list = [ 
    ('id', '42'), 
    ('name', '"the entity"'), 
    ('some_attr', '{"one": 1, "two": 2}'), 
] 
apply_values(entity, attr_list) 

x = entity.id 
print(x, type(x)) 
x = entity.name 
print(x, type(x)) 
x = entity.some_attr 
print(x, type(x)) 

Ausgang

42 <class 'int'> 
the entity <class 'str'> 
{'one': 1, 'two': 2} <class 'dict'> 

Beachten Sie, dass wir auch die Attributnamen & Wert Strings in ein dict setzen können:

attr_dict = { 
    'id': '42', 
    'name': '"the entity"', 
    'some_attr': '{"one": 1, "two": 2}' 
} 

apply_values(entity, attr_dict.items()) 

Wie Alfe in den Kommentaren erwähnt, ignoriert dieser Code den Typ der Attribute der Entität. Hier ist eine modifizierte Version, die die vorhandenen Attributtypen berücksichtigt.

import ast 

class SomeEntity: 
    def __init__(self): 
     self.id = 0 
     self.name = "" 
     self.some_attr = {} 
     self.level = 0.0 

def apply_values(entity, list_of_values): 
    for key, value in list_of_values: 
     if hasattr(entity, key): 
      type_attr = type(getattr(entity, key)) 
      converted = type_attr(ast.literal_eval(value)) 
      setattr(entity, key, converted) 

entity = SomeEntity() 

attr_dict = { 
    'id': '42', 
    'name': '"the entity"', 
    'some_attr': '{"one": 1, "two": 2}', 
    'level': '5', 
} 

apply_values(entity, attr_dict.items()) 

for k, v in entity.__dict__.items(): 
    print(repr(k), repr(v), type(v)) 

Ausgang

'id' 42 <class 'int'> 
'name' 'the entity' <class 'str'> 
'some_attr' {'one': 1, 'two': 2} <class 'dict'> 
'level' 5.0 <class 'float'> 
+0

Dies wird eine 'int' für die Eingabe setzen' „5“ 'in eine Variable, die eine' float' halten soll. Aber ich denke, in den meisten Fällen ist das kein Problem. For¹ für die Verwendung von 'ast.literal_eval()', obwohl es eindeutig jenseits der OP-Ebene liegt. – Alfe

+0

@Alfe Guter Punkt. Ich werde meiner Antwort noch mehr Code hinzufügen. –

+0

Vielen Dank! es funktioniert perfekt für mich – arthas

0

viele Fehler in Garjy Lösung Befestigung:

converted = eval(value) 

Vielleicht möchten Sie es auf den richtigen Typ explizit danach konvertieren:

converted type(getattr(entity, key))(eval(value)) 

So ganz in einer Zeile:

setattr(entity, key, type(getattr(entity, key))(eval(value)))