TL;DR Die beste Lösung ist s.replace('.','',1).isdigit()
Ich habe einige Benchmarks Vergleich der verschiedenen Ansätze
def is_number_tryexcept(s):
""" Returns True is string is a number. """
try:
float(s)
return True
except ValueError:
return False
import re
def is_number_regex(s):
""" Returns True is string is a number. """
if re.match("^\d+?\.\d+?$", s) is None:
return s.isdigit()
return True
def is_number_repl_isdigit(s):
""" Returns True is string is a number. """
return s.replace('.','',1).isdigit()
Wenn die Zeichenkette keine Zahl ist, ist der except-Block recht langsam. Noch wichtiger ist jedoch, dass die try-except-Methode der einzige Ansatz ist, der wissenschaftliche Notationen korrekt behandelt.
funcs = [
is_number_tryexcept,
is_number_regex,
is_number_repl_isdigit
]
a_float = '.1234'
print('Float notation ".1234" is not supported by:')
for f in funcs:
if not f(a_float):
print('\t -', f.__name__)
Die Float-Notation ".1234" wird nicht unterstützt von:
- is_number_regex
scientific1 = '1.000000e+50'
scientific2 = '1e50'
print('Scientific notation "1.000000e+50" is not supported by:')
for f in funcs:
if not f(scientific1):
print('\t -', f.__name__)
print('Scientific notation "1e50" is not supported by:')
for f in funcs:
if not f(scientific2):
print('\t -', f.__name__)
Die wissenschaftliche Notation "1.000000e+50" wird nicht unterstützt von:
- is_number_regex
- is_number_repl_isdigit
Die wissenschaftliche Notation "1e50" wird nicht unterstützt von:
- is_number_regex
- is_number_repl_isdigit
EDIT: Die Benchmark-Ergebnisse
import timeit
test_cases = ['1.12345', '1.12.345', 'abc12345', '12345']
times_n = {f.__name__:[] for f in funcs}
for t in test_cases:
for f in funcs:
f = f.__name__
times_n[f].append(min(timeit.Timer('%s(t)' %f,
'from __main__ import %s, t' %f)
.repeat(repeat=3, number=1000000)))
wobei die folgenden Funktionen getestet wurden
from re import match as re_match
from re import compile as re_compile
def is_number_tryexcept(s):
""" Returns True is string is a number. """
try:
float(s)
return True
except ValueError:
return False
def is_number_regex(s):
""" Returns True is string is a number. """
if re_match("^\d+?\.\d+?$", s) is None:
return s.isdigit()
return True
comp = re_compile("^\d+?\.\d+?$")
def compiled_regex(s):
""" Returns True is string is a number. """
if comp.match(s) is None:
return s.isdigit()
return True
def is_number_repl_isdigit(s):
""" Returns True is string is a number. """
return s.replace('.','',1).isdigit()
101 Stimmen
Was ist falsch an Ihrer derzeitigen Lösung? Sie ist kurz, schnell und lesbar.
7 Stimmen
Und Sie müssen nicht nur True oder False zurückgeben. Sie können stattdessen den Wert entsprechend modifiziert zurückgeben - zum Beispiel könnten Sie dies verwenden, um Nicht-Zahlen in Anführungszeichen zu setzen.
10 Stimmen
Wäre es nicht besser, im Falle einer erfolgreichen Konvertierung das Ergebnis von float(s) zurückzugeben? Sie haben immer noch die Erfolgsprüfung (Ergebnis ist False) und Sie haben die Umwandlung, die Sie wahrscheinlich sowieso wollen.
0 Stimmen
Thruston - Ich verstehe, was Sie meinen, aber dann ist die Prüfung nicht mehr so einfach.
12 Stimmen
Auch wenn diese Frage schon älter ist, wollte ich nur sagen, dass dies ein eleganter Weg ist, der dokumentiert ist als EAFP . Das ist wahrscheinlich die beste Lösung für diese Art von Problem.
2 Stimmen
Das scheint in Ordnung zu sein, es sei denn, Sie validieren die Eingaben eines Benutzers, da locale.atoi("0,1,00") 100.... ergibt.
0 Stimmen
Sehr nützliche Funktion. Darüber hinaus, wenn Sie Raum, wie 1e + 2, etc. zulassen wollen, dann muss diese Funktion geändert werden.
0 Stimmen
Wenn Sie nicht wissen, ob es sich bei dem Eingabewert um eine Zeichenkette handelt, können Sie auch einen TypeError
2 Stimmen
pythoncentral.io/ würde helfen.
0 Stimmen
Gibt das Ergebnis von
float(s)
bei Erfolg, oderNone
, bei Fail. Dann erhalten Sie das True/False-Verhalten und können das Ergebnis direkt verwenden.0 Stimmen
Verwandt: Float/Double-Wert extrahieren
10 Stimmen
Nicht gibt das Ergebnis von float(s) oder None bei Fail zurück. Wenn Sie es dann als
x = float('0.00'); if x: use_float(x);
haben Sie jetzt einen Fehler in Ihrem Code. Wahrheitsgemäße Werte sind der Grund dafür, dass diese Funktionen eine Ausnahme auslösen und nicht zurückgebenNone
an erster Stelle. Eine bessere Lösung ist es, die Hilfsfunktion zu vermeiden und den Aufruf von float in einetry catch
wenn Sie es benutzen wollen.0 Stimmen
Dies ist ein Teil des Problems, das in dem Beitrag stackoverflow.com/questions/36903462/adding-numbers-in-a-string/
4 Stimmen
Achtung: Das Snippet sagt aus, dass jede Objekt, das automatisch wirft zu float ist eine Zahl, und das könnte irreführend sein. Zum Beispiel kann eine einfache bool ist eine Zahl, da float(True) eine gültige 1,0 zurückgibt.
0 Stimmen
Nicht langsam. int(s) oder float(s) ist wahrscheinlich fast so schnell wie das, was der Python-Interpreter für solche Dinge verwendet und kann sogar etwas C-Code darunter haben. In [17]: time_it(int, '333', count=1) Out[17]: 4.0531158447265625e-06 Ziemlich schnell.
0 Stimmen
Wahrscheinlich möchten Sie den ValueError-Teil loswerden, da dieser sonst eine Ausnahme auslöst, wenn er eine Liste / ein Diktat als Eingabe erhält
0 Stimmen
@Colonel Panic es ist auch langsam
2 Stimmen
Der langsame Teil ist NICHT der Float(a). Der langsame Teil ist die Ausnahme throw/catch. Wie jeder gute Programmierer weiß: VERWENDEN SIE NIEMALS AUSNAHMEN FÜR DEN NORMALEN CODE-WEG. Der OP hat das nicht spezifiziert, also denke ich, dass wir davon ausgehen sollten, dass nicht-numerische Eingaben "normal" für diese Funktion sind. Ist es in Python üblich, Ausnahmen als Teil des normalen Codeflusses zu verwenden? @SamanthaAtkins
0 Stimmen
Warum nicht folgen lazy Überprüfung Muster? davon ausgehen, dass das Objekt ein Float ist und versuchen Sie die Operation und fangen eine Ausnahme, protokollieren Sie es und dann gießen Sie es zu Float und reattempt.