2013-03-12 15 views

risposta

20
def isfloat(x): 
    try: 
     a = float(x) 
    except ValueError: 
     return False 
    else: 
     return True 

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

Naturalmente, si dovrebbe testare per 'isint()' prima, e quindi testare per 'isfloat()' solo se il primo restituisce 'False'. –

+0

Beh prima prova isint, e poi usa isfloat, ma, se uso isint, tutti i test vengono passati. Pensi che sia meglio usare isint() solo? – ManuParra

+1

Questo è sbagliato per numeri molto grandi. Ad esempio, float ("10000000000000000.5") è 1e + 16, int (1e + 16) è 1e + 16, tuttavia il numero non è un int. – Nixon

12

pitone float oggetti hanno un is_integer method:

from ast import literal_eval 
def parses_to_integer(s): 
    val = literal_eval(s) 
    return isinstance(val, int) or (isinstance(val, float) and val.is_integer()) 
+0

Preferisco questo metodo in quanto non fa affidamento su un'eccezione come parte della valutazione. – DaveL17

+0

se s non valuta un valore letterale valido, genera un errore. Inoltre, "False" tornerà come un numero intero che potrebbe non essere quello che desideri. So che stai rispondendo direttamente alla domanda dell'utente, quindi la tua soluzione è valida ma qualsiasi trappola per topi può essere migliorata. – shrewmouse

3
def coerce(x): 
    try: 
     a = float(x) 
     b = int(x) 
     if a == b: 
      return b 
     else: 
      return a 
    except: 
     raise ValueError("failed to coerce str to int or float") 
+0

Questo fallirà per i float. Se 'x == 0.5', la riga' b = int (x) 'genererà immediatamente un'eccezione ValueError e il condizionale' if a == b' non verrà mai eseguito. – daveruinseverything

0

ho dovuto gestire il caso di assicurare che '1,0' viene convertito a '1' quando ha cercato di determinare le differenze tra due documenti XML. Così ho scritto questa funzione per aiutarmi. Penso anche che alcune delle altre soluzioni falliranno quando il letterale stringa in questione è 'True' o 'False'. Ad ogni modo questa funzione funziona molto bene per me. Spero che ti possa aiutare anche tu.

from ast import literal_eval 

def convertString(s): 
    ''' 
    This function will try to convert a string literal to a number or a bool 
    such that '1.0' and '1' will both return 1. 

    The point of this is to ensure that '1.0' and '1' return as int(1) and that 
    'False' and 'True' are returned as bools not numbers. 

    This is useful for generating text that may contain numbers for diff 
    purposes. For example you may want to dump two XML documents to text files 
    then do a diff. In this case you would want <blah value='1.0'/> to match 
    <blah value='1'/>. 

    The solution for me is to convert the 1.0 to 1 so that diff doesn't see a 
    difference. 

    If s doesn't evaluate to a literal then s will simply be returned UNLESS the 
    literal is a float with no fractional part. (i.e. 1.0 will become 1) 

    If s evaluates to float or a float literal (i.e. '1.1') then a float will be 
    returned if and only if the float has no fractional part. 

    if s evaluates as a valid literal then the literal will be returned. (e.g. 
    '1' will become 1 and 'False' will become False) 
    ''' 


    if isinstance(s, str): 
     # It's a string. Does it represnt a literal? 
     # 
     try: 
      val = literal_eval(s) 
     except: 
      # s doesn't represnt any sort of literal so no conversion will be 
      # done. 
      # 
      val = s 
    else: 
     # It's already something other than a string 
     # 
     val = s 

    ## 
    # Is the float actually an int? (i.e. is the float 1.0 ?) 
    # 
    if isinstance(val, float): 
     if val.is_integer(): 
      return int(val) 

     # It really is a float 
     return val 

    return val 

L'uscita del test dell'unità di questa funzione produce: il codice di prova

convertString("1")=1; we expect 1 
convertString("1.0")=1; we expect 1 
convertString("1.1")=1.1; we expect 1.1 
convertString("010")=8; we expect 8 
convertString("0xDEADBEEF")=3735928559; we expect 3735928559 
convertString("hello")="hello"; we expect "hello" 
convertString("false")="false"; we expect "false" 
convertString("true")="true"; we expect "true" 
convertString("False")=False; we expect False 
convertString("True")=True; we expect True 
convertString(sri.gui3.xmlSamples.test_convertString.A)=sri.gui3.xmlSamples.test_convertString.A; we expect sri.gui3.xmlSamples.test_convertString.A 
convertString(<function B at 0x7fd9e2f27ed8>)=<function B at 0x7fd9e2f27ed8>; we expect <function B at 0x7fd9e2f27ed8> 
convertString(1)=1; we expect 1 
convertString(1.0)=1; we expect 1 
convertString(1.1)=1.1; we expect 1.1 
convertString(3735928559)=3735928559; we expect 3735928559 
convertString(False)=False; we expect False 
convertString(True)=True; we expect True 

L'apparecchio segue:

import unittest 

# just class for testing that the class gets returned unmolested. 
# 
class A: pass 

# Just a function 
# 
def B(): pass 

class Test(unittest.TestCase): 


    def setUp(self): 
     self.conversions = [ 
      # input  | expected 
      ('1'   ,1  ), 
      ('1.0'  ,1  ), # float with no fractional part 
      ('1.1'  ,1.1  ), 
      ('010'  ,8  ), # octal 
      ('0xDEADBEEF',0xDEADBEEF), # hex 
      ('hello'  ,'hello' ), 
      ('false'  ,'false' ), 
      ('true'  ,'true' ), 
      ('False'  ,False ), # bool 
      ('True'  ,True  ), # bool 
      (A   ,A  ), # class 
      (B   ,B  ), # function 
      (1   ,1  ), 
      (1.0   ,1  ), # float with no fractional part 
      (1.1   ,1.1  ), 
      (0xDEADBEEF ,0xDEADBEEF), 
      (False  ,False ), 
      (True  ,True  ), 
     ] 


    def testName(self): 
     for s,expected in self.conversions: 
      rval = convertString(s) 
      print 'convertString({s})={rval}; we expect {expected}'.format(**locals()) 
      self.assertEqual(rval, expected) 


if __name__ == "__main__": 
    #import sys;sys.argv = ['', 'Test.testName'] 
    unittest.main() 
0

Ecco una soluzione interessante utilizzando eval(). Nota: l'utilizzo di eval è altamente pericoloso e non è raccomandato in ambienti di produzione o in qualsiasi luogo in cui eval() possa ricevere input da parte dell'utente! Considera questa una risposta solo accademicamente interessante.

def get_string_type(x): 
    if type(x) != str: 
     raise ValueError('Input must be a string!') 
    try: 
     string_type = type(eval(x)) 
    except NameError: 
     string_type = str 
    return string_type 

Poiché Eval tratta la stringa come codice raw, funziona per qualsiasi tipo che è possibile immettere in un repl. Esempio

>>> from decimal import Decimal 
>>> my_test_string = 'Decimal(0.5)' 
>>> type(my_test_string) 
<class 'str'> 
>>> get_string_type(my_test_string) 
<class 'decimal.Decimal'>