2015-10-13 8 views
8

Quando digito int("1.7") Python restituisce un errore (in particolare, ValueError). So che posso convertirlo in numero intero di int(float("1.7")). Mi piacerebbe sapere perché il primo metodo restituisce un errore.Perché non è possibile convertire "1.7" in intero direttamente, senza prima convertire in float?

+1

I numeri interi in virgola mobile si comportano in modo diverso sui computer. È raro mischiarli allo stesso scopo. Quindi il comportamento di Python ti impedisce di commettere errori. – Nayuki

+1

I perché int tratta le stringhe in modo diverso rispetto ai float ... tronca i float ... ma controlla le stringhe solo per le cifre (lo spazio bianco alle estremità è ok) –

+0

Python tenta di prevenire i bug sottili e questa funzione li incoraggerebbe. Immagina: chiedi a Bob per la sua età. Bob pensa "Sto compiendo 18 anni il prossimo mese" ed entra in 17.9, che il tuo codice non si aspettava. Vuoi buttare fuori quel 0.9 o vuoi segnalare un errore, in modo che Bob aggiusti il ​​suo input o correggi il codice? Uno dei motti di Python è "Gli errori non devono passare in silenzio, a meno che non siano esplicitamente messi a tacere: di fronte all'ambiguità, rifiutare la tentazione di indovinare". La tua funzionalità va contro quella linea guida, quindi Python non lo fa. Per ulteriori parole di saggezza, digita "importa questo". –

risposta

9

Dal documentation:

Se x non è un numero o se viene data base, allora x deve essere una stringa o un oggetto Unicode rappresenta un letterale intero nella base di radice ...

Ovviamente, "1.7" non rappresenta un numero intero letterale in base radix.

Se vuoi sapere perché gli sviluppatori di python hanno deciso di limitarsi ai letterali interi in base radix, ci sono un numero infinito di motivi e dovresti chiedere a Guido et. per sapere per certo. Un'ipotesi sarebbe la facilità di implementazione + l'efficienza. Si potrebbe pensare che sarebbe stato facile per loro di attuare come:

  1. Interpret numero come un galleggiante
  2. troncato in un intero

Purtroppo, che non funziona in Python come interi può hanno precisione arbitraria e non possono farlo i float. Numeri grandi di involucri speciali potrebbero portare a inefficienze per il caso comune .

Inoltre, costringendo lo fai per int(float(...)) ha l'ulteriore vantaggio in termini di chiarezza - Lo rende più evidente ciò che la stringa di input probabilmente sembra che può aiutare nel debug altrove. In effetti, potrei obiettare che anche se accetterebbe stringhe come "1.7", sarebbe meglio scrivere int(float("1.7")) in ogni caso per aumentare la chiarezza del codice.

Presupposto per la convalida. Altre lingue salta questo - ad es. ruby valuterà '1e6'.to_i e fornirà 1 poiché smette di analizzare il primo carattere non integrale. Sembra che potrebbe portare a bug divertenti da rintracciare ...

+2

Non penso che abbia nulla a che fare con il fatto che 'int' è una precisione arbitraria. In Ruby, '" 1.7 ".to_i' ==' 1'. Smettono semplicemente di analizzare il primo carattere non valido. Penso che sia solo una delle chiamate di Guido per aiutare a prevenire i bug difficili da rilevare. –

+2

Forse. Ma sembra che sarebbe un giorno abbastanza sorprendente per me se 'int ('cento babbuini')' risultasse in '1' (che, è quello che l'equivalente di rubino ti darebbe se sto capendo correttamente il tuo commento). Suppongo che l'analisi senza alcuna convalida possa essere molto più veloce - ma è proprio quello che vuoi? (e la risposta a questa domanda è anche una delle ragioni per cui abbiamo così tanti linguaggi di programmazione con diversi modi di pensare, ecc.) – mgilson

+0

Non è quello che voglio. Volevo rubare per sollevare un'eccezione quando stavo facendo qualcosa del genere l'altro giorno. A volte la magia si intromette. Sono felice di essere esplicito in casi come questi. –

1

Ecco una buona descrizione del perché non è possibile farlo presente nella documentazione di Python.

https://docs.python.org/2/library/functions.html#int

Se x non è un numero o se viene data base, allora x deve essere una stringa o un oggetto Unicode rappresenta un letterale intero nella base di radice. Opzionalmente, il letterale può essere preceduto da + o - (senza spazio intermedio) e circondato da spazi bianchi. Un letterale di base-n è costituito dalle cifre da 0 a n-1, con dalla a alla z (o dalla A alla Z) con valori da 10 a 35. La base predefinita è 10. I valori consentiti sono 0 e 2-36. Base-2, -8 e -16 letterali possono essere opzionalmente preceduti da 0b/0B, 0o/0O/0 o 0x/0X, come per i letterali interi nel codice. Base 0 significa interpretare la stringa esattamente come un intero letterale, in modo che la base reale è 2, 8, 10, o 16.

Fondamentalmente typecast a un numero intero da una stringa, la stringa non deve contenere "."

+0

Strettamente, non si tratta solo se il numero contiene "." La notazione scientifica potrebbe anche rompere l'intimità della stringa. Esempi: 'int (" 6e7 ")' non è un numero intero (base-10). Comunque 'int (" 6e7 ", 16)' = 1767 è un numero intero in base-16 (o qualsiasi base> = 15). Ma 'int (" 6e-7 ")' non è mai un int in nessuna base. – smci

2

abbiamo una buona idea evidente di ciò che 'fare un int da questa float' mezzi perché pensiamo di un galleggiante come due parti e possiamo gettare uno di loro via.

Non è così ovvio quando abbiamo una stringa. Trasforma questa stringa in un oggetto mobile implica tutti i tipi di cose sottili sul contenuto della stringa e non è il tipo di cosa che una persona sana di mente vuole vedere nel codice in cui il valore non è ovvio

Quindi la risposta breve è: a Python piacciono le cose ovvie e scoraggia la magia

1

Interruzioni indietro -compatibilità. È è certamente possibile, tuttavia questa sarebbe una pessima idea dal momento che romperebbe all'indietro-compatibilità con l'idioma Python molto vecchio e consolidato di fare affidamento su una prova ... eccetto ladder ("Più facile chiedere perdono che il permesso ") per determinare il tipo di contenuto della stringa. Questo idioma è stato utilizzato e utilizzato almeno da Python 1.5, AFAIK; ecco due citazioni: [1][2]

s = "foo12.7" 
#s = "-12.7" 
#s = -12 

try: 
    n = int(s) # or else throw an exception if non-integer... 
    print "Do integer stuff with", n 
except ValueError: 
    try: 
     f = float(s) # or else throw an exception if non-float... 
     print "Do float stuff with", f 
    except ValueError: 
     print "Handle case for when s is neither float nor integer" 
     raise # if you want to reraise the exception 

E un'altra cosa minore: non si tratta solo di se il numero contiene '' La notazione scientifica, o lettere arbitrarie, potrebbe anche rompere l'intimità della stringa. Esempi: int("6e7") non è un numero intero (base-10). Tuttavia int("6e7",16) = 1767 è un numero intero in base-16 (o qualsiasi base> = 15). Ma int("6e-7") non è mai un int.

(E se si espande la base su base-36, qualsiasi stringa alfanumerica legale (o Unicode) può essere interpretata come rappresentativa di un intero, ma farlo per impostazione predefinita sarebbe generalmente un comportamento terribile, poiché "cane" o " cat "è improbabile che siano riferimenti a numeri interi).

Problemi correlati