2016-04-07 8 views
1

ich api Anrufe machte und eine Antwort zurück in json erhalten wie soSmart-Type-Casting in Python

result = {'foo': '123.456', 'bar': '23', 'donald': 'trump', 'time': '2016-04-07T05:31:49.532124Z'} 

Obwohl Ergebnis ist entweder ein Wörterbuch oder eine Liste, sind die Inhalte immer Strings. Ich möchte diese Werte auf den entsprechenden Typ umwandeln. (Das heißt '123.456' mit einem Schwimmer, '23' in einem int, 'time' zu einem Datetime.)

Mein Code funktioniert, aber es scheint, wie es sollte eine einfachere/effizientere Art und Weise, dies zu tun. Ist da?

Hier ist meine Version

from dateutil.parser import parse 

def is_float(x): 
    try: 
     float(x) 
     return True 
    except ValueError: 
     return False 

def is_int(x): 
    try: 
     a = float(x) 
     b = int(a) 
    except ValueError: 
     return False 
    else: 
     return a == b 

def is_datetime(x): 
    try: 
     parse(x) 
     return True 
    except ValueError: 
     return False 

def smartcast(x): 
    if isinstance(x, dict): 
     return { k:smartcast(v) for k, v in x.items() } 
    elif isinstance(x, list): 
     return map(smartcast, x) 
    elif is_int(x): 
     return int(x) 
    elif is_float(x): 
     return float(x) 
    elif is_datetime(x): 
     return parse(x) 
    else: 
     return x 

Edit: Wenn möglich, dass ich mit try und except vermeiden möchten. Ich möchte dies in einem asynchronen verdrehten Programm implementieren und ich denke try und except Block, so dass es nur das Programm synchron macht. Ich bin neu zu verdreht, also bin ich mir nicht sicher, ob das stimmt.


Wie Francesco-Lösung, hier ist der aktualisierte Code.

from dateutil.parser import parse 

def smartcast(x): 
    if isinstance(x, dict): 
     return { k:smartcast(v) for k, v in x.items() } 
    elif isinstance(x, list): 
     return map(smartcast, x) 
    else: 
     for t in [int, float, parse]: 
      try: 
       return t(x) 
      except ValueError: 
       continue 
    return x 
+0

'und ich denke, versuchen und außer Block' - warum denkst du so? Es blockiert nicht, die Ausnahmebehandlung hat nichts mit dem Blockieren zu tun. – mata

+0

Ich war mir nicht sicher, wie es solche Ausnahmen behandelte. Ich denke, es blockiert nicht. Ich war verwirrt, weil du normalerweise ein 'Depered' mit einem' .errback' verwendest und ich wusste nicht, wie unterschiedlich das von einem 'except' oder einem' raise' war. –

Antwort

3

Und was ist die geeignete Art? Ich frage dies zu unterstreichen, dass manchmal auch für Menschen ist nicht klar, was der Typ ist: Sind Sie sicher, dass "42" immer ein int ist oder manchmal muss es nur als eine Zeichenfolge betrachtet werden?

Wie auch immer, Sie können Ihre Lösung mit Ihren Regeln erstellen, die in Ihrem Kontext sinnvoll sind.

In Ihrem Fall können Sie Ihren Code mit einer einfachen Schleife

from dateutil.parser import parse 

tests = [int, float, parse] 

def smartcast(value): 
    for test in tests: 
     try: 
      return test(value) 
     except ValueError: 
      continue 
    # No match 
    return value 
+0

'Lambda-Wert: parse (Wert)' ist das gleiche wie nur 'Parse' – mata

+0

danke, ich verbesserte das Beispiel mit Ihrem Kommentar! – Francesco