2010-05-18 11 views
10

biorąc pod uwagę listę ciągów Pythona, w jaki sposób mogę automatycznie przekonwertować je na ich poprawny typ? Co oznacza, jeśli miećKonwertowanie listy smyczków do ich typów

["hello", "3", "3.64", "-1"] 

ja tego być przekształcany do listy

["hello", 3, 3.64, -1] 

, gdy pierwszy element jest stirng drugi int trzeci pływaka i czwarty i int.

Jak mogę to zrobić? dzięki.

Odpowiedz

20
import ast 

L = ["hello", "3", "3.64", "-1"] 

def tryeval(val): 
    try: 
    val = ast.literal_eval(val) 
    except ValueError: 
    pass 
    return val 

print [tryeval(x) for x in L] 
+4

W uczciwości, to jest lepsze rozwiązanie niż moje. – jemfinch

+0

ale evals są nieco hackish i przejęte – msw

+1

Jeśli jest wystarczająco dobre dla kompilatora Python, to jest wystarczająco dobre dla użytkownika. –

3
def tryEval(s): 
    try: 
    return eval(s, {}, {}) 
    except: 
    return s 

map(tryEval, ["hello", "3", "3.64", "-1"]) 

to zrobić tylko wtedy, gdy ufasz wejście. Należy także pamiętać, że obsługuje on więcej niż tylko literały; Wyrażenia arytmetyczne będą również oceniane.

+0

Powinieneś określić typy wyjątków (np. NameError, SyntaxError). – tgray

+0

Ogólnie rzecz biorąc, tak, ale w tej implementacji zdecydowanie nie. Czy naprawdę chcesz podjąć próbę określenia * wszystkich * wyjątków, które mogą zostać podniesione przez 'eval'? ZeroDivisionError, TypeError, i prawdopodobnie trochę więcej, o czym nawet nie myślę? – jemfinch

8

Bez użycia ocena:

def convert(val): 
    constructors = [int, float, str] 
    for c in constructors: 
     try: 
      return c(val) 
     except ValueError: 
      pass 
+2

+1 Unikaj używania eval dodaj wszystkie koszty – manifest

+1

+1 pythonically – msw

+1

Świetne rozwiązanie (i bezpieczne!). Podejście można z łatwością rozszerzyć na dowolny typ danych. +1 – Escualo

0

Jeśli jesteś naprawdę zainteresowany tylko strun, pływaków, a ints, wolę bardziej gadatliwy, mniej evalful

def interpret_constant(c): 
    try: 
     if str(int(c)) == c: return int(c) 
    except ValueError: 
     pass 
    try: 
     if str(float(c)) == c: return float(c) 
    except ValueError: 
     return c 

test_list = ["hello", "3", "3.64", "-1"] 

typed_list = [interpret_constant(x) for x in test_list] 
print typed_list 
print [type(x) for x in typed_list] 
0

To nie jest naprawdę Odpowiedź, ale chciałem wskazać, jak ważne może to być, gdy masz bazę danych parametrów ze schematem ID, PAR, VAL. Na przykład:

ID PAR  VAL 
001 velocity '123.45' 
001 name  'my_name' 
001 date  '18-dec-1978' 

Ten schemat jest właściwy kiedy nie wiem ile parametry trzeba przechowywać przez pewien ID. Wadą jest właśnie to, że wartości w VAL są ciągami i muszą zostać przekonwertowane na właściwy typ danych na żądanie. Możesz to zrobić, dodając czwartą kolumnę do schematu o nazwie TYPE lub możesz użyć dowolnego z zaproponowanych do tej pory podejść.

Dobre pytanie!

PS. Schemat bazy danych jest powiązany z one of my previous questions.

0

Wariant ładnym rozwiązania Ryans męska, dla NumPy użytkowników:

def tonum(x): 
    """ -> int(x)/float(x)/None/x as is """ 
    if np.isscalar(x): # np.int8 np.float32 ... 
    # if isinstance(x, (int, long, float)): 
     return x 
    try: 
     return int(x, 0) # 0: "0xhex" too 
    except ValueError: 
     try: 
      return float(x) # strings nan, inf and -inf too 
     except ValueError: 
      if x == "None": 
       return None 
      return x 

def numsplit(line, sep=None): 
    """ line -> [nums or strings ...] """ 
    return map(tonum, line.split(sep)) # sep None: whitespace 
1

osiągnąłem to samo używając json.loads metodę

def f(l): 
    for i in l: 
     try: 
      yield json.loads(i) 
     except: 
      yield i 

Test:

In [40]: l 
Out[40]: ['hello', '3', '3.64', '-1'] 

In [41]: list(f(l)) 
Out[41]: ['hello', 3, 3.64, -1] 
Powiązane problemy