Wie kann ich überprüfen, ob ein String eine Zahl (float) ist?
-
20-08-2019 - |
Frage
Was ist die beste Art und Weise zu überprüfen, ob eine Zeichenfolge als Zahl in Python dargestellt werden?
Die Funktion, die ich zur Zeit gerade jetzt haben, ist:
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
Welche, nicht nur hässlich und langsam ist, scheint klobig. Allerdings habe ich keine bessere Methode, weil Aufruf float
in der Hauptfunktion ist noch schlimmer gefunden.
Lösung
Welche, ist nicht nur hässlich und langsam
Ich würde beide streitig zu machen.
Ein regex oder andere Zeichenfolgenanalyse Methode wäre hässlich und langsamer.
Ich bin nicht sicher, dass alles viel schneller sein kann als die oben genannten. Es ruft die Funktion und kehrt zurück. Try / Catch nicht viel Aufwand nicht einführen, weil die häufigste Ausnahme ohne eine umfangreiche Suche von Stack-Frames gefangen wird.
Das Problem ist, dass jede numerische Konvertierungsfunktion zwei Arten von Ergebnissen hat
- Eine Zahl, wenn die Zahl gültig
- Ein Statuscode (zum Beispiel über errno) oder eine Ausnahme zeigen, dass keine gültige Zahl analysiert werden kann.
C (als Beispiel) hackt um dieses eine Reihe von Möglichkeiten. Python legt es klar und deutlich aus.
Ich denke, Ihr Code, dies zu tun perfekt ist.
Andere Tipps
Falls Sie suchen Parsen (positiv, unsigned) ganze Zahlen anstelle von Schwimmern, können Sie die isdigit()
Funktion für String-Objekte.
>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False
String-Methoden - isdigit()
: Python2 , Python3
Es gibt auch etwas auf Unicode-Strings, die ich nicht allzu vertraut bin mit Unicode - Ist Dezimal / dezimal
TL; DR Die beste Lösung ist s.replace('.','',1).isdigit()
Ich habe einige Benchmarks die verschiedenen Ansätze zu vergleichen
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 Zeichenfolge nicht eine Zahl ist, die außer-Block ist ziemlich langsam. Aber noch wichtiger ist, die try-except-Methode ist der einzige Ansatz, richtig wissenschaftliche Notationen 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__)
:
Float-Notation“0,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__)
Wissenschaftliche Notation "1.000000e + 50" wird nicht unterstützt durch:
- is_number_regex
- is_number_repl_isdigit
: 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)))
Dabei gilt folgende 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()
Es gibt eine Ausnahme, die Sie vielleicht berücksichtigen: die Zeichenfolge ‚NaN‘
Wenn Sie is_number FALSCH zurück für ‚NaN‘ dieser Code wird nicht funktionieren, wie Python wandelt sie in ihrer Darstellung einer Zahl, die keine Zahl ist (Diskussion über Identitätsfragen):
>>> float('NaN')
nan
Ansonsten sollte ich Sie eigentlich danken für das Stück Code, den ich jetzt ausgiebig nutzen. :)
G.
Wie wäre es dieses:
'3.14'.replace('.','',1).isdigit()
, die nur wahr zurück, wenn es eine oder keine ‚‘ in der Folge von Ziffern.
'3.14.5'.replace('.','',1).isdigit()
wird return false
edit: gerade gesehen, einen weiteren Kommentar ...
eine .replace(badstuff,'',maxnum_badstuff)
für andere Fälle Zugabe getan werden kann. wenn Sie Salz sind vorbei und nicht willkürlich Würzmittel (ref: xkcd # 974 ), wird dies tun gut: P
Aktualisiert nach Alfe wies darauf hin, Sie müssen nicht für Schwimmer separat als komplexe Griffe überprüfen beide:
def is_number(s):
try:
complex(s) # for int, long, float and complex
except ValueError:
return False
return True
vorher gesagt: Sind einige seltenen Fälle, die Sie auch für komplexe Zahlen überprüfen, müssen möglicherweise (z 1 + 2i), die durch einen Schwimmer dargestellt werden kann:
def is_number(s):
try:
float(s) # for int, long and float
except ValueError:
try:
complex(s) # for complex
except ValueError:
return False
return True
Welche, ist nicht nur hässlich und langsam, klobig zu sein scheint.
Es kann etwas gewöhnungsbedürftig, aber das ist die pythonic Art und Weise tun. Wie bereits darauf hingewiesen wurde, sind die Alternativen schlechter. Aber es gibt einen anderen Vorteil der Dinge auf diese Weise zu tun. Polymorphismus
Die zentrale Idee hinter Duck Typing ist, dass „wenn es wie eine Ente geht und spricht, dann ist es eine Ente.“ Was passiert, wenn Sie entscheiden, dass Sie Zeichenfolge Unterklasse benötigen, so dass Sie ändern können, wie Sie feststellen, ob etwas in einem Schwimmer umgerechnet werden können? Oder was, wenn Sie sich entscheiden, ganz ein anderes Objekt zu testen? Sie können diese Dinge tun, ohne den obigen Code ändern zu müssen.
Andere Sprachen lösen diese Probleme durch Schnittstellen. Ich werde die Analyse davon sparen Lösung besser für einen anderen Thread ist. Der Punkt ist aber, dass Python entschieden auf die Ente Typisierung Seite der Gleichung ist, und Sie sind wahrscheinlich wie diese gehen zu müssen, gewöhnen Syntax, wenn Sie auf dem Tun viel Programmierung in Python planen (aber das bedeutet nicht, Sie haben es natürlich mögen).
Eine andere Sache, die Sie wollen vielleicht berücksichtigen: Python ist ziemlich schnell in Werfen und Ausnahmen im Vergleich zu vielen anderen Sprachen (30x schneller als .Net zum Beispiel) zu kontrollieren. Heck, die Sprache selbst wirft auch Ausnahmen kommunizieren nicht außergewöhnlich, normale Programmbedingungen (jedes Mal, wenn Sie eine for-Schleife). So würde ich nicht zu viele Sorgen über die Leistungsaspekte dieses Codes, bis Sie ein erhebliches Problem bemerken.
Für int
verwenden:
>>> "1221323".isdigit()
True
Aber für float
brauchen wir ein paar Tricks ;-). Jeder Schwimmer Nummer hat einen Punkt ...
>>> "12.34".isdigit()
False
>>> "12.34".replace('.','',1).isdigit()
True
>>> "12.3.4".replace('.','',1).isdigit()
False
Auch für negative Zahlen addieren gerade lstrip()
:
>>> '-12'.lstrip('-')
'12'
Und jetzt bekommen wir eine universelle Art und Weise:
>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False
Just Mimic C #
In C # gibt es zwei verschiedene Funktionen, die skalare Werte Griff Parsen:
- Float.Parse ()
- Float.TryParse ()
float.parse ():
def parse(string):
try:
return float(string)
except Exception:
throw TypeError
Hinweis: Wenn Sie sich fragen, warum ich die Ausnahme von einem Typeerror geändert, hier ist die Dokumentation .
float.try_parse ():
def try_parse(string, fail=None):
try:
return float(string)
except Exception:
return fail;
Hinweis: Sie wollen nicht die boolean ‚False‘ zurück, weil das immer noch ein Werttyp ist. Keiner ist besser, weil es Fehler anzeigt. Natürlich, wenn Sie etwas anderes wollen, können Sie die Parameter zum Scheitern verurteilt ändern, was auch immer Sie wollen.
Schwimmer Zur Verlängerung der ‚Parse ()‘ schließen und ‚try_parse ()‘ müssen Sie die ‚schweben‘ Klasse monkeypatch diese Methoden hinzuzufügen.
Wenn Sie respektieren wollen, dass der Code bereits bestehende Funktionen sollte wie etwas sein:
def monkey_patch():
if(!hasattr(float, 'parse')):
float.parse = parse
if(!hasattr(float, 'try_parse')):
float.try_parse = try_parse
Sidenote:. Ich persönlich lieber nennen Affe Stanzen, weil es fühlt sich an wie ich die Sprache bin zu missbrauchen, wenn ich dies tun, aber YMMV
Verwendung:
float.parse('giggity') // throws TypeException
float.parse('54.3') // returns the scalar value 54.3
float.tryParse('twank') // returns None
float.tryParse('32.2') // returns the scalar value 32.2
Und die große, sagte Sage Pythonas beim Heiligen Stuhl Sharpisus „Alles, was Sie mich besser tun kann, tun können;. Ich kann besser als Sie etwas tun“
Bei Strings von Nicht-Zahlen, try: except:
ist tatsächlich langsamer als regulärer Ausdrücke. Bei Strings gültiger Zahlen ist regex langsamer. So hängt die entsprechende Methode auf Ihre Eingabe.
Wenn Sie feststellen, dass Sie in einer Performance binden sind, können Sie ein neues Dritt Modul fastnumbers , dass bietet eine Funktion namens isfloat . Vollständige Offenlegung, ich bin der Autor. Ich habe unten in den Zeiten ihre Ergebnisse enthält.
from __future__ import print_function
import timeit
prep_base = '''\
x = 'invalid'
y = '5402'
z = '4.754e3'
'''
prep_try_method = '''\
def is_number_try(val):
try:
float(val)
return True
except ValueError:
return False
'''
prep_re_method = '''\
import re
float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match
def is_number_re(val):
return bool(float_match(val))
'''
fn_method = '''\
from fastnumbers import isfloat
'''
print('Try with non-number strings', timeit.timeit('is_number_try(x)',
prep_base + prep_try_method), 'seconds')
print('Try with integer strings', timeit.timeit('is_number_try(y)',
prep_base + prep_try_method), 'seconds')
print('Try with float strings', timeit.timeit('is_number_try(z)',
prep_base + prep_try_method), 'seconds')
print()
print('Regex with non-number strings', timeit.timeit('is_number_re(x)',
prep_base + prep_re_method), 'seconds')
print('Regex with integer strings', timeit.timeit('is_number_re(y)',
prep_base + prep_re_method), 'seconds')
print('Regex with float strings', timeit.timeit('is_number_re(z)',
prep_base + prep_re_method), 'seconds')
print()
print('fastnumbers with non-number strings', timeit.timeit('isfloat(x)',
prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with integer strings', timeit.timeit('isfloat(y)',
prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with float strings', timeit.timeit('isfloat(z)',
prep_base + 'from fastnumbers import isfloat'), 'seconds')
print()
Try with non-number strings 2.39108395576 seconds
Try with integer strings 0.375686168671 seconds
Try with float strings 0.369210958481 seconds
Regex with non-number strings 0.748660802841 seconds
Regex with integer strings 1.02021503448 seconds
Regex with float strings 1.08564686775 seconds
fastnumbers with non-number strings 0.174362897873 seconds
fastnumbers with integer strings 0.179651021957 seconds
fastnumbers with float strings 0.20222902298 seconds
Wie Sie sehen
-
try: except:
war schnell für numerische Eingaben aber sehr langsam für eine ungültige Eingabe - regex ist sehr effizient, wenn die Eingabe ungültig ist
-
fastnumbers
gewinnt in beiden Fällen
Ich weiß, das besonders alt ist, aber ich würde eine Antwort Ich glaube, deckt die Informationen hinzufügen, fehlen die höchste Antwort gestimmt, die zu einem sehr wertvoll sein könnten, die diese finden:
Für jede der folgenden Methoden, um sie mit einer Zählung verbinden, wenn Sie jede Eingabe müssen in Kauf genommen werden. (Vorausgesetzt, wir sind mit Stimm Definitionen von ganzen Zahlen anstatt 0-255, etc.)
x.isdigit()
wenn x funktioniert gut für die Überprüfung eine ganze Zahl ist.
x.replace('-','').isdigit()
eignet sich gut für die Überprüfung, ob x ein negativ ist (Check - in der ersten Position).
x.replace('.','').isdigit()
eignet sich gut für die Überprüfung, ob x eine Dezimalzahl ist.
x.replace(':','').isdigit()
eignet sich gut für die Überprüfung, ob x ein Verhältnis ist.
x.replace('/','',1).isdigit()
eignet sich gut für die Überprüfung, ob x eine Fraktion ist.
Casting zu schweben und zu kontrollieren ist wahrscheinlich Valueerror der schnellste Weg, da Schwimmer (), die speziell für genau das gemeint ist. Alles andere, die String-Parsing (regex, etc.) erfordert wird wahrscheinlich langsamer sein aufgrund der Tatsache, dass es für diese Operation nicht abgestimmt ist. My $ 0,02.
Sie können Unicode-Strings verwenden, sie haben eine Methode genau das zu tun, was Sie wollen:
>>> s = u"345"
>>> s.isnumeric()
True
Oder:
>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True
Diese Antwort stellt Schritt für Schritt Anleitung mit Beispielen, die Funktion die Zeichenfolge zu finden ist:
- Positive integer
- Positiv / Negativ - integer / float
- Wie verwerfen "NaN" (keine Zahl) Saiten, während für Nummernprüfung?
Überprüfen Sie, ob Zeichenfolge positive integer
Sie können verwenden str.isdigit()
prüfen, ob gegebene Zeichenfolge positive integer.
Proben Ergebnisse:
# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False
Nach Zeichenfolge als positiv / negativ - integer / float
str.isdigit()
kehren False
wenn die Zeichenfolge eine negativ Zahl oder eine Gleitkommazahl. Zum Beispiel:
# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False
Wenn Sie auf überprüfen Sie auch für die negativ Zahlen und float
, dann können Sie eine benutzerdefinierte Funktion schreiben für sie zu überprüfen, wie:
def is_number(n):
try:
float(n) # Type-casting the string to `float`.
# If string is not a valid `float`,
# it'll raise `ValueError` exception
except ValueError:
return False
return True
Beispiel Run:
>>> is_number('123') # positive integer number
True
>>> is_number('123.4') # positive float number
True
>>> is_number('-123') # negative integer number
True
>>> is_number('-123.4') # negative `float` number
True
>>> is_number('abc') # `False` for "some random" string
False
Discard "NaN" (keine Zahl) Saiten, während für Nummernprüfung
Die obigen Funktionen zurückkehren True
für die „NAN“ (Not a number) Zeichenfolge, weil für Python ist gültig Schwimmer repräsentiert es keine Zahl ist. Zum Beispiel:
>>> is_number('NaN')
True
Um zu überprüfen, ob die Zahl "NaN", können Sie math.isnan()
wie:
>>> import math
>>> nan_num = float('nan')
>>> math.isnan(nan_num)
True
Oder wenn Sie importieren möchten dies keine zusätzliche Bibliothek zu überprüfen, dann können Sie einfach überprüfen sie es mit sich selbst über den Vergleich mit ==
. Python kehrt False
wenn nan
Schwimmer mit sich selbst verglichen. Zum Beispiel:
# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False
Daher oben Funktion is_number
aktualisiert werden kann False
für "NaN"
zurückzukehren wie:
def is_number(n):
is_number = True
try:
num = float(n)
# check for "nan" floats
is_number = num == num # or use `math.isnan(num)`
except ValueError:
is_number = False
return is_number
Beispiel Run:
>>> is_number('Nan') # not a number "Nan" string
False
>>> is_number('nan') # not a number string "nan" with all lower cased
False
>>> is_number('123') # positive integer
True
>>> is_number('-123') # negative integer
True
>>> is_number('-1.12') # negative `float`
True
>>> is_number('abc') # "some random" string
False
PS: Jede Operation für jede Kontrolle über die Art der Zahl abhängig kommt mit zusätzlichen Overhead. Wählen Sie die Version von is_number
Funktion, die Ihre Anforderung passt.
Ich wollte sehen, welche Methode ist am schnellsten. Insgesamt sind die besten und beständigsten Ergebnisse wurden durch die check_replace
Funktion gegeben. Die schnellsten Ergebnisse der check_exception
Funktion gegeben wurden, aber nur, wenn es keine Ausnahme gefeuert -. Seinen Code Bedeutung der effizienteste ist, aber der Aufwand für das Auslösen einer Ausnahme ist recht groß
Bitte beachten Sie, dass für eine erfolgreiche Besetzung Überprüfung der einzige Methode ist, die genau ist, zum Beispiel, das funktioniert mit check_exception
aber die andere beiden Testfunktionen werden falsch für einen gültigen Schwimmer zurück:
huge_number = float('1e+100')
Hier ist der Benchmark-Code:
import time, re, random, string
ITERATIONS = 10000000
class Timer:
def __enter__(self):
self.start = time.clock()
return self
def __exit__(self, *args):
self.end = time.clock()
self.interval = self.end - self.start
def check_regexp(x):
return re.compile("^\d*\.?\d*$").match(x) is not None
def check_replace(x):
return x.replace('.','',1).isdigit()
def check_exception(s):
try:
float(s)
return True
except ValueError:
return False
to_check = [check_regexp, check_replace, check_exception]
print('preparing data...')
good_numbers = [
str(random.random() / random.random())
for x in range(ITERATIONS)]
bad_numbers = ['.' + x for x in good_numbers]
strings = [
''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10)))
for x in range(ITERATIONS)]
print('running test...')
for func in to_check:
with Timer() as t:
for x in good_numbers:
res = func(x)
print('%s with good floats: %s' % (func.__name__, t.interval))
with Timer() as t:
for x in bad_numbers:
res = func(x)
print('%s with bad floats: %s' % (func.__name__, t.interval))
with Timer() as t:
for x in strings:
res = func(x)
print('%s with strings: %s' % (func.__name__, t.interval))
Hier sind die Ergebnisse mit Python 2.7.10 auf einem 2017 MacBook Pro 13:
check_regexp with good floats: 12.688639
check_regexp with bad floats: 11.624862
check_regexp with strings: 11.349414
check_replace with good floats: 4.419841
check_replace with bad floats: 4.294909
check_replace with strings: 4.086358
check_exception with good floats: 3.276668
check_exception with bad floats: 13.843092
check_exception with strings: 15.786169
Hier sind die Ergebnisse mit Python 3.6.5 auf einem 2017 MacBook Pro 13:
check_regexp with good floats: 13.472906000000009
check_regexp with bad floats: 12.977665000000016
check_regexp with strings: 12.417542999999995
check_replace with good floats: 6.011045999999993
check_replace with bad floats: 4.849356
check_replace with strings: 4.282754000000011
check_exception with good floats: 6.039081999999979
check_exception with bad floats: 9.322753000000006
check_exception with strings: 9.952595000000002
Hier sind die Ergebnisse mit PyPy 2.7.13 auf einem 2017 MacBook Pro 13:
check_regexp with good floats: 2.693217
check_regexp with bad floats: 2.744819
check_regexp with strings: 2.532414
check_replace with good floats: 0.604367
check_replace with bad floats: 0.538169
check_replace with strings: 0.598664
check_exception with good floats: 1.944103
check_exception with bad floats: 2.449182
check_exception with strings: 2.200056
Also um es alle zusammen, für Nan Überprüfung, Unendlichkeit und komplexe Zahlen (es scheint sie mit j angegeben sind, nicht i, das heißt 1 + 2j) führt dies zu:
def is_number(s):
try:
n=str(float(s))
if n == "nan" or n=="inf" or n=="-inf" : return False
except ValueError:
try:
complex(s) # for complex
except ValueError:
return False
return True
Ich habe einige Geschwindigkeitstests. Lassen Sie uns sagen, dass, wenn die Zeichenfolge ist wahrscheinlich eine Zahl die try / except sein Strategie ist die schnellste possible.If die Zeichenfolge ist nicht wahrscheinlich, eine Zahl und Sie interessieren sich für Integer überprüfen, lohnt es einige Test (isdigit Plus Überschrift '-') zu tun. Wenn Sie Interesse zu prüfen float Zahl sind, müssen Sie die try / except Code whitout Flucht.
ich brauchte, um zu bestimmen, ob ein String in Grundtypen gegossen (float, int, str, bool). Nach nicht alles auf dem Internet zu finden, habe ich dies:
def str_to_type (s):
""" Get possible cast type for a string
Parameters
----------
s : string
Returns
-------
float,int,str,bool : type
Depending on what it can be cast to
"""
try:
f = float(s)
if "." not in s:
return int
return float
except ValueError:
value = s.upper()
if value == "TRUE" or value == "FALSE":
return bool
return type(s)
Beispiel
str_to_type("true") # bool
str_to_type("6.0") # float
str_to_type("6") # int
str_to_type("6abc") # str
str_to_type(u"6abc") # unicode
Sie können die Art erfassen und es verwenden,
s = "6.0"
type_ = str_to_type(s) # float
f = type_(s)
Die Eingabe kann wie folgt aussehen:
a="50"
b=50
c=50.1
d="50.1"
1 General Eingang:
Die Eingabe dieser Funktion kann alles sein!
Prüft, ob die gegebene Variable numerisch ist. Numerische Strings bestehen aus optionalen Vorzeichen, eine beliebige Anzahl von Ziffern, optional Dezimalteil und optional exponentiellen Teil. So + 0123.45e6 ist ein gültiger numerischer Wert. Hexadezimal (z 0xf4c3b00c) und binäre (z 0b10100111001) Notation ist nicht erlaubt.
is_numeric Funktion
import ast
import numbers
def is_numeric(obj):
if isinstance(obj, numbers.Number):
return True
elif isinstance(obj, str):
nodes = list(ast.walk(ast.parse(obj)))[1:]
if not isinstance(nodes[0], ast.Expr):
return False
if not isinstance(nodes[-1], ast.Num):
return False
nodes = nodes[1:-1]
for i in range(len(nodes)):
#if used + or - in digit :
if i % 2 == 0:
if not isinstance(nodes[i], ast.UnaryOp):
return False
else:
if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
return False
return True
else:
return False
Test:
>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True
is_float Funktion
Prüft, ob die gegebene Variable float ist. Schwimmer Saiten bestehen aus optionalen Vorzeichen, eine beliebige Anzahl von Ziffern, ...
import ast
def is_float(obj):
if isinstance(obj, float):
return True
if isinstance(obj, int):
return False
elif isinstance(obj, str):
nodes = list(ast.walk(ast.parse(obj)))[1:]
if not isinstance(nodes[0], ast.Expr):
return False
if not isinstance(nodes[-1], ast.Num):
return False
if not isinstance(nodes[-1].n, float):
return False
nodes = nodes[1:-1]
for i in range(len(nodes)):
if i % 2 == 0:
if not isinstance(nodes[i], ast.UnaryOp):
return False
else:
if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
return False
return True
else:
return False
Test:
>>> is_float("5.4")
True
>>> is_float("5")
False
>>> is_float(5)
False
>>> is_float("5")
False
>>> is_float("+5.4")
True
Was ist ast ?
2- Wenn Sie sicher sind, dass das variable Gehalt String :
str.isdigit () Methode
>>> a=454
>>> a.isdigit()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'isdigit'
>>> a="454"
>>> a.isdigit()
True
3-numerische Eingabe:
erkennen int-Wert:
>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>>
erkennen float:
>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True
Ryann schlägt
Wenn Sie für eine NaN und Inf, ändern Linie x = float Falsch zurück (s); return (x == x) und (x - 1 = x). Dies sollte für alle Schwimmer außer Inf und NaN return true
Aber das funktioniert nicht ganz, denn für ausreichend großen Schwimmer, x-1 == x
true zurück. Zum Beispiel 2.0**54 - 1 == 2.0**54
Ich denke, Ihre Lösung ist in Ordnung.
Having said that, es gibt eine Menge von regexp Hass auf diese Antworten, die ich denke nicht gerechtfertigt ist, kann regexps maßen sauber und korrekt und schnell sein. Es hängt wirklich davon ab, was Sie zu tun versuchen. Die ursprüngliche Frage war, wie können Sie „überprüfen, ob eine Zeichenfolge als Zahl (float) dargestellt werden“ (wie pro Ihren Titel). Vermutlich würden Sie den numerischen / float-Wert benutzen, wenn Sie überprüft haben, dass es gültig ist, wobei in diesem Fall Ihre Try / außer sehr viel Sinn macht. Aber wenn aus irgendeinem Grund, Sie wollen einfach nur bestätigen, dass ein string ist eine Zahl dann auch eine Regex funktioniert gut, aber es ist schwer, richtig zu erhalten. Ich denke, die meisten der regex Antworten bisher zum Beispiel nicht richtig Strings ohne einen ganzzahligen Teil analysiert (wie zum Beispiel“0,7" ), die einen Schwimmer ist so weit wie Python angeht. Und das ist etwas heikel für in einem einzigen regulären Ausdruck zu prüfen, wo der Bruchteil ist nicht erforderlich. Ich habe zwei Regex enthalten, dies zu zeigen.
Es tut die interessante Frage auf, was eine „Nummer“ ist. Haben Sie „inf“ enthalten, die als Schwimmer in Python gültig ist? Oder haben Sie Nummern enthalten, die „Zahlen“ sind aber vielleicht nicht in Python dargestellt werden (wie Zahlen, die größer ist als der Schwimmer max sind).
Es gibt auch Unklarheiten, wie Sie Zahlen analysieren. Zum Beispiel, was ist mit „--20“? Ist dies eine „Nummer“? Ist dies ein legaler Weg „20“ zu vertreten? Python lassen Sie tun „var = --20“ und legen Sie es auf 20 (obwohl wirklich das ist, weil sie es als Ausdruck behandelt), aber Schwimmer. ( „- 20“) funktioniert nicht
Wie auch immer, ohne weitere Informationen, hier ist ein regulärer Ausdruck, dass ich glaube, deckt alle ints und schwimmt als Python sie parst .
# Doesn't properly handle floats missing the integer part, such as ".7"
SIMPLE_FLOAT_REGEXP = re.compile(r'^[-+]?[0-9]+\.?[0-9]+([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56" # sign (-)
# integer (12)
# mantissa (34)
# exponent (E+56)
# Should handle all floats
FLOAT_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56" # sign (-)
# integer (12)
# OR
# int/mantissa (12.34)
# exponent (E+56)
def is_float(str):
return True if FLOAT_REGEXP.match(str) else False
Einige Beispiel-Testwerte:
True <- +42
True <- +42.42
False <- +42.42.22
True <- +42.42e22
True <- +42.42E-22
False <- +42.42e-22.8
True <- .42
False <- 42nope
Ich habe auch die Funktion, die Sie erwähnten, aber bald merke ich, dass Strings als „Nan“, „Inf“ und es ist Variation als Zahl betrachtet. Also schlage ich vor, Sie Version Ihrer Funktion verbessert, die auf jene Art von Eingabe false zurück und wird nicht scheitern „1e3“ Varianten:
def is_float(text):
try:
float(text)
# check for nan/infinity etc.
if text.isalpha():
return False
return True
except ValueError:
return False
import re
def is_number(num):
pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
result = pattern.match(num)
if result:
return True
else:
return False
>>>: is_number('1')
True
>>>: is_number('111')
True
>>>: is_number('11.1')
True
>>>: is_number('-11.1')
True
>>>: is_number('inf')
False
>>>: is_number('-inf')
False
Dieser Code behandelt die Exponenten, den Schwimmer und ganze Zahlen, ohne Regex.
return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False
Hier ist meine einfache Art und Weise tun. Lassen Sie uns sagen, dass ich durch einige Saiten bin Looping und ich möchte, dass sie zu einem Array hinzuzufügen, wenn sie sich als Zahlen.
try:
myvar.append( float(string_to_check) )
except:
continue
Setzen Sie die myvar.apppend mit dem, was den Betrieb wollen Sie mit der Zeichenfolge zu tun, wenn sich herausstellt, eine Nummer zu sein. Die Idee ist, zu versuchen, einen Schwimmer () Betrieb zu verwenden, und den zurückgegebene Fehler verwenden, um zu bestimmen, ob die Zeichenfolge eine Zahl ist.
Sie können durch Rücksendung nützliche Werte als Wahr und Falsch, die Ausnahme-Technik in einer sinnvollen Weise verallgemeinern. Zum Beispiel setzt diese Funktion Zitate runden Schnüre lässt aber Zahlen allein. Das ist genau das, was ich für einen schnellen und schmutzige Filter benötigt, um einige variable Definitionen für R.
machenimport sys
def fix_quotes(s):
try:
float(s)
return s
except ValueError:
return '"{0}"'.format(s)
for line in sys.stdin:
input = line.split()
print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'
Ich war an einem Problem arbeiten, die mich auf diesen Thread geführt, nämlich wie eine Sammlung von Daten in Strings und Zahlen in der meisten intuitiven Art und Weise zu konvertieren. Ich erkennen nach dem ursprünglichen Code zu lesen, dass, was ich brauchte in zweierlei Hinsicht anders war:
1 - Ich wollte ein ganzzahliges Ergebnis, wenn die Zeichenfolge eine ganze Zahl repräsentiert
2 - Ich wollte eine Zahl oder eine Zeichenkette Ergebnis in eine Datenstruktur zu halten
so angepasst ich den Original-Code, um dieses Derivat zu erzeugen:
def string_or_number(s):
try:
z = int(s)
return z
except ValueError:
try:
z = float(s)
return z
except ValueError:
return s
Versuchen Sie dies.
def is_number(var):
try:
if var == int(var):
return True
except Exception:
return False
Benutzerhilfsfunktion:
def if_ok(fn, string):
try:
return fn(string)
except Exception as e:
return None
dann
if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])
Verwendung folgender es behandelt alle Fälle: -
import re
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '2.3')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '2.')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '.3')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '2.3sd')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' , '2.3')