Wie überprüfe ich, ob eine Zeichenfolge eine Zahl ist (float)?

1608

Wie kann am besten überprüft werden, ob eine Zeichenfolge in Python als Zahl dargestellt werden kann?

Die Funktion, die ich derzeit habe, ist:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

Was nicht nur hässlich und langsam ist, sondern auch klobig erscheint. Ich habe jedoch keine bessere Methode gefunden, da das Aufrufen floatder Hauptfunktion noch schlimmer ist.

Daniel Goldberg
quelle
61
Was ist los mit Ihrer aktuellen Lösung? Es ist kurz, schnell und lesbar.
Colonel Panic
5
Und Sie müssen nicht nur True oder False zurückgeben. Sie können stattdessen den entsprechend geänderten Wert zurückgeben. Sie können diesen beispielsweise verwenden, um Nicht-Zahlen in Anführungszeichen zu setzen.
Thruston
7
Wäre es bei einer erfolgreichen Konvertierung nicht besser, das Ergebnis von float (s) zurückzugeben? Sie haben immer noch die Prüfung auf Erfolg (Ergebnis ist False) und Sie haben tatsächlich die Konvertierung, die Sie wahrscheinlich sowieso wollen.
Jiminion
8
Obwohl diese Frage älter ist, wollte ich nur sagen, dass dies ein eleganter Weg ist, der als EAFP dokumentiert ist . Also wahrscheinlich die beste Lösung für diese Art von Problem.
Thiruvenkadam
7
Geben Sie das Ergebnis von float (s) oder None on fail nicht zurück. Wenn Sie es dann verwenden, haben x = float('0.00'); if x: use_float(x);Sie jetzt einen Fehler in Ihrem Code. Wahrheitswerte sind der Grund, warum diese Funktionen eine Ausnahme auslösen, anstatt überhaupt zurückzukehren None. Eine bessere Lösung besteht darin, die Dienstprogrammfunktion zu vermeiden und den Aufruf zu umgeben, um in einem zu schweben, try catchwenn Sie ihn verwenden möchten.
ovangle

Antworten:

699

Was nicht nur hässlich und langsam ist

Ich würde beides bestreiten.

Ein Regex oder eine andere String-Parsing-Methode wäre hässlicher und langsamer.

Ich bin mir nicht sicher, ob etwas viel schneller sein könnte als oben. Es ruft die Funktion auf und kehrt zurück. Try / Catch verursacht nicht viel Overhead, da die häufigste Ausnahme ohne umfangreiche Suche nach Stapelrahmen abgefangen wird.

Das Problem ist, dass jede numerische Konvertierungsfunktion zwei Arten von Ergebnissen hat

  • Eine Nummer, wenn die Nummer gültig ist
  • Ein Statuscode (z. B. über errno) oder eine Ausnahme, um anzuzeigen, dass keine gültige Nummer analysiert werden konnte.

C (als Beispiel) hackt dies auf verschiedene Arten. Python legt es klar und explizit dar.

Ich denke, Ihr Code dafür ist perfekt.

S.Lott
quelle
21
Ich denke nicht, dass der Code perfekt ist (aber ich denke, dass er sehr nahe ist): Es ist üblicher, nur den Teil, der "getestet" wird, in die tryKlausel aufzunehmen, also würde ich den return Truein eine elseKlausel der setzen try. Einer der Gründe ist, dass ich mit dem Code in der Frage, wenn ich ihn überprüfen müsste, überprüfen müsste, ob die zweite Anweisung in der tryKlausel keinen ValueError auslösen kann: Zugegeben, dies erfordert nicht zu viel Zeit oder Gehirnleistung. aber warum welche verwenden, wenn keine benötigt wird?
Eric O Lebigot
4
Die Antwort scheint überzeugend, aber ich frage mich, warum sie nicht sofort verfügbar ist ... Ich werde sie kopieren und auf jeden Fall verwenden.
Salbei
9
Wie schrecklich. Wie wäre es, wenn es mir egal ist, was die Nummer ist, nur dass es eine Nummer ist (was mich hierher gebracht hat)? Anstelle einer 1-Zeile habe IsNumeric()ich entweder einen Versuch / Fang oder einen anderen, der einen Versuch / Fang einwickelt. Ugh
Basic
6
Es wird nicht "out of the box" bereitgestellt, da if is_number(s): x = float(x) else: // failes die gleiche Anzahl von Codezeilen wie das enthält try: x = float(x) catch TypeError: # fail. Diese Utility-Funktion ist eine völlig unnötige Abstraktion.
ovangle
12
Aber Abstraktion ist der springende Punkt bei Bibliotheken. Eine 'isNumber'-Funktion (in jeder Sprache) hilft sehr viel, da Sie sie direkt in if-Anweisungen einbauen können und über weitaus besser lesbaren und wartbaren Code verfügen, der auf try-catch-Blöcken basiert. Wenn Sie den Code mehr als einmal in mehr als einer Klasse / einem Modul verwenden müssen, haben Sie mehr Codezeilen verwendet, als eine integrierte Funktion hätte.
JamEngulfer
1612

Wenn Sie nach Ganzzahlen (positive, vorzeichenlose) Ganzzahlen anstelle von Gleitkommazahlen suchen, können Sie die isdigit()Funktion für Zeichenfolgenobjekte verwenden.

>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False

String-Methoden - isdigit(): Python2 , Python3

Es gibt auch etwas in Unicode-Zeichenfolgen, mit dem ich mit Unicode nicht allzu vertraut bin - Ist dezimal / dezimal

Zoomulator
quelle
232
Das ist auch ein Negativ für Negative
Intrepion
22
Schlägt auch mit Exponentialen fehl: '1e3'.isdigit () -> False
ssc
35
Während Number! = Digit, können Personen, die nach Möglichkeiten suchen, um zu testen, ob eine Zeichenfolge eine Ganzzahl enthält, über diese Frage stolpern, und der isDigit-Ansatz ist möglicherweise perfekt für ihre Anwendung geeignet.
Adam Parkin
8
@AdamParkin: isdigit()und int()haben unterschiedliche Meinungen darüber, was eine ganze Zahl ist, z. B. für das Unicode-Zeichen u'\u00b9': u'¹'.isdigit()ist Trueaber int(u'¹')erhöht ValueError.
JFS
6
+1: isdigit () ist vielleicht nicht das, wonach das OP gesucht hat, aber es ist genau das, was ich wollte. Es mag sein, dass diese Antwort und Methode nicht alle Arten von Zahlen abdeckt, aber sie ist entgegen den Argumenten über ihre Genauigkeit immer noch von hoher Relevanz. Während "Zahl! = Ziffer" ist die Ziffer immer noch eine Teilmenge der Zahl, insbesondere Zahlen, die positiv oder nicht negativ sind und die Basis 1-10 verwenden. Darüber hinaus ist diese Methode besonders nützlich und kurz für Fälle, in denen Sie überprüfen möchten, ob eine Zeichenfolge eine numerische ID ist oder nicht, die häufig in die soeben beschriebene Teilmenge von Zahlen fällt.
Justin Johnson
161

TL; DR Die beste Lösung ists.replace('.','',1).isdigit()

Ich habe einige Benchmarks durchgeführt , um 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 keine Zahl ist, ist der Ausnahmeblock ziemlich 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)))

wo 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()

Geben Sie hier die Bildbeschreibung ein

Idok
quelle
15
für schöne Charts +1. Ich sah Benchmark und sah Grafik, die ganze TL; DR-Sache wurde klar und intuitiv.
Jcchuks
Ich stimme @JCChuks zu: Die Grafik hilft sehr dabei, alle TL; DR schnell zu erhalten. Aber ich denke, ein TL; DR (wie: TL; DR : die beste Lösung ist s.replace('.','',1).isdigit()) sollte am Anfang dieser Antwort erscheinen. In jedem Fall sollte es das akzeptierte sein. Vielen Dank!
Simon C.
10
Diese Methode verarbeitet keine negativen Zahlen (Bindestriche). Ich würde empfehlen, nur die Float-Methode zu verwenden, da sie weniger fehleranfällig ist und jedes Mal funktioniert.
Urchin
3
Es ist wichtig zu beachten, dass selbst unter der Annahme, dass es keinen Bindestrich geben kann, die Methode replace-isdigit nur für Nicht-Zahlen schneller ist (falsches Ergebnis), während die Methode try-without für Zahlen schneller ist (True result). Wenn der größte Teil Ihrer Eingabe eine gültige Eingabe ist, ist die Try-Except-Lösung besser geeignet!
Markus von Broady
1
Funktioniert nicht mit exponentieller Notation wie '1.5e-9'oder mit Negativen.
EL_DON
68

Es gibt eine Ausnahme, die Sie möglicherweise berücksichtigen möchten: die Zeichenfolge 'NaN'

Wenn Sie möchten, dass is_number FALSE für 'NaN' zurückgibt, funktioniert dieser Code nicht, da Python ihn in die Darstellung einer Zahl konvertiert, die keine Zahl ist (sprechen Sie über Identitätsprobleme):

>>> float('NaN')
nan

Ansonsten sollte ich mich bei Ihnen für den Code bedanken, den ich jetzt ausgiebig benutze. :) :)

G.

gvrocha
quelle
2
Tatsächlich NaNkönnte es ein guter Wert sein, (anstatt False) zurückzugeben, wenn der übergebene Text tatsächlich keine Darstellung einer Zahl ist. Das Überprüfen darauf ist eine Art Schmerz (Pythons floatTyp benötigt wirklich eine Methode dafür), aber Sie können es in Berechnungen verwenden, ohne einen Fehler zu erzeugen, und müssen nur das Ergebnis überprüfen.
Kindall
7
Eine weitere Ausnahme ist die Zeichenfolge 'inf'. Entweder infoder NaNkann auch mit einem +oder vorangestellt werden -und wird trotzdem akzeptiert.
Agf
4
Wenn Sie für NaN und Inf False zurückgeben möchten, ändern Sie die Zeile in x = float (s); return (x == x) und (x - 1! = x). Dies sollte True für alle Floats außer Inf und NaN
RyanN
5
x-1 == xgilt für große schwimmer kleiner als inf. In Python 3.2 können Sie math.isfinitenach Zahlen suchen, die weder NaN noch unendlich sind, oder beide math.isnanund math.isinfdavor überprüfen .
Steve Jessop
56

Wie wäre es damit:

'3.14'.replace('.','',1).isdigit()

was nur dann true zurückgibt, wenn es ein oder kein '.' gibt. in der Ziffernfolge.

'3.14.5'.replace('.','',1).isdigit()

wird false zurückgeben

edit: habe gerade einen weiteren Kommentar gesehen ... das Hinzufügen eines .replace(badstuff,'',maxnum_badstuff)für andere Fälle kann durchgeführt werden. Wenn Sie Salz und keine willkürlichen Gewürze geben (Ref: xkcd # 974 ), reicht dies aus: P.

haxwithaxe
quelle
7
Dies berücksichtigt jedoch keine negativen Zahlen.
Michael Barton
5
Oder Zahlen mit Exponenten wie 1.234e56(die auch als +1.234E+56und mehrere weitere Varianten geschrieben werden könnten ).
Alfe
re.match(r'^[+-]*(0[xbo])?[0-9A-Fa-f]*\.?[0-9A-Fa-f]*(E[+-]*[0-9A-Fa-f]+)$', 'str')sollte eine Zahl besser bestimmen (aber nicht alle, das behaupte ich nicht). Ich empfehle nicht, dies zu verwenden, weitaus besser, den Originalcode des Fragestellers zu verwenden.
Baldrickk
wenn Sie diese Lösung nicht, lesen Sie diese vor dem Downvoting!
Aloisdg Umzug auf codidact.com
Mann, das ist die klügste Lösung, die ich je auf dieser Website gesehen habe!
Karam Qusai
41

Was nicht nur hässlich und langsam ist, sondern auch klobig erscheint.

Es mag etwas gewöhnungsbedürftig sein, aber dies ist die pythonische Art, es zu tun. Wie bereits erwähnt, sind die Alternativen schlechter. Aber es gibt noch einen weiteren Vorteil, wenn man die Dinge so macht: Polymorphismus.

Die zentrale Idee hinter dem Tippen von Enten ist: "Wenn es wie eine Ente geht und spricht, dann ist es eine Ente." Was ist, wenn Sie entscheiden, dass Sie eine Zeichenfolge unterordnen müssen, damit Sie ändern können, wie Sie bestimmen, ob etwas in einen Float konvertiert werden kann? Oder was ist, wenn Sie sich entscheiden, ein anderes Objekt vollständig zu testen? Sie können diese Dinge tun, ohne den obigen Code ändern zu müssen.

Andere Sprachen lösen diese Probleme mithilfe von Schnittstellen. Ich werde die Analyse speichern, welche Lösung für einen anderen Thread besser ist. Der Punkt ist jedoch, dass Python entschieden auf der Seite der Ententypisierung der Gleichung steht und Sie sich wahrscheinlich an eine solche Syntax gewöhnen müssen, wenn Sie viel in Python programmieren möchten (aber das bedeutet nicht, dass dies der Fall ist du musst es natürlich mögen).

Eine andere Sache, die Sie vielleicht berücksichtigen sollten: Python ist im Vergleich zu vielen anderen Sprachen (30x schneller als beispielsweise .Net) ziemlich schnell beim Auslösen und Abfangen von Ausnahmen. Heck, die Sprache selbst löst sogar Ausnahmen aus, um nicht außergewöhnliche, normale Programmbedingungen zu kommunizieren (jedes Mal, wenn Sie eine for-Schleife verwenden). Daher würde ich mich nicht zu sehr um die Leistungsaspekte dieses Codes kümmern, bis Sie ein signifikantes Problem bemerken.

Jason Baker
quelle
1
Ein weiterer häufiger Ort, an dem Python Ausnahmen für Grundfunktionen verwendet, ist hasattr()ein getattr()Aufruf, der in a eingeschlossen ist try/except. Die Ausnahmebehandlung ist jedoch langsamer als die normale Flusskontrolle. Wenn Sie sie daher für etwas verwenden, das die meiste Zeit zutrifft, kann dies zu Leistungseinbußen führen.
Kindall
Es scheint, dass, wenn Sie einen Einzeiler wollen, Sie SOL
Basic
Pythonisch ist auch die Idee, dass es "besser ist, um Vergebung als um Erlaubnis zu bitten", was die Auswirkungen billiger Ausnahmen betrifft.
Heltonbiker
40

Aktualisiert, nachdem Alfe darauf hingewiesen hat, dass Sie nicht separat nach Float suchen müssen, da beide komplexe Handles:

def is_number(s):
    try:
        complex(s) # for int, long, float and complex
    except ValueError:
        return False

    return True

Zuvor gesagt: In einigen seltenen Fällen müssen Sie möglicherweise auch nach komplexen Zahlen suchen (z. B. 1 + 2i), die nicht durch einen Float dargestellt werden können:

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
Matthew Wilcoxson
quelle
14
Ich stimme dir nicht zu. Dies ist bei normaler Verwendung SEHR unwahrscheinlich, und Sie sollten einen is_complex_number () -Aufruf erstellen, wenn Sie sie verwenden, anstatt einen Aufruf mit zusätzlichen Operationen zu belasten, um eine Wahrscheinlichkeit von 0,0001% für Fehloperationen zu erhalten.
Jiminion
3
Sie können das float()Zeug komplett entfernen und einfach prüfen, ob der complex()Anruf erfolgreich ist. Alles, was analysiert wird, float()kann analysiert werden complex().
Alfe
Diese Funktion gibt die NaN- und Inf-Werte von Pandas als numerische Werte zurück.
Fixxxer
complex('(01989)')wird zurückkehren (1989+0j). Aber float('(01989)')wird fehlschlagen. Daher denke ich, dass die Verwendung complexkeine gute Idee ist.
Plhn
26

Zur intVerwendung:

>>> "1221323".isdigit()
True

Aber dafür floatbrauchen wir ein paar Tricks ;-). Jede Float-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 einfach hinzufügen lstrip():

>>> '-12'.lstrip('-')
'12'

Und jetzt bekommen wir einen universellen Weg:

>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False
Sdwdaw
quelle
2
Behandelt keine 1.234e56ähnlichen Dinge . Außerdem würde mich interessieren, wie Sie herausfinden würden, dass dies 99999999999999999999e99999999999999999999keine Zahl ist. Der Versuch, es zu analysieren, findet es schnell heraus.
Alfe
Dies läuft ~ 30% schneller als die akzeptierte Lösung auf einer Liste von 50-m-Strings und 150% schneller auf einer Liste von 5k-Strings. 👏
Zev Averbach
15

Nur Mimic C #

In C # gibt es zwei verschiedene Funktionen, die das Parsen von Skalarwerten handhaben:

  • 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 in einen TypeError geändert habe, finden Sie hier die Dokumentation .

float.try_parse ():

def try_parse(string, fail=None):
    try:
        return float(string)
    except Exception:
        return fail;

Hinweis: Sie möchten den booleschen Wert "False" nicht zurückgeben, da dies immer noch ein Werttyp ist. Keiner ist besser, weil er auf einen Fehler hinweist. Wenn Sie etwas anderes wollen, können Sie den Parameter fail natürlich nach Belieben ändern.

Um float um 'parse ()' und 'try_parse ()' zu erweitern, müssen Sie die 'float'-Klasse monkeypatchen, um diese Methoden hinzuzufügen.

Wenn Sie bereits vorhandene Funktionen respektieren möchten, sollte der Code wie folgt aussehen:

def monkey_patch():
    if(!hasattr(float, 'parse')):
        float.parse = parse
    if(!hasattr(float, 'try_parse')):
        float.try_parse = try_parse

SideNote: Ich persönlich bevorzuge es Monkey Punching zu nennen, weil es sich anfühlt, als würde ich die Sprache missbrauchen, wenn ich das mache, aber YMMV.

Verwendungszweck:

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 der große Weise Pythonas sagte zu dem Heiligen Stuhl Sharpisus: "Alles, was du tun kannst, kann ich besser machen; ich kann alles besser machen als du."

Evan Scholle
quelle
Ich habe in letzter Zeit hauptsächlich in JS programmiert und dies nicht wirklich getestet, so dass es einige kleinere Fehler geben kann. Wenn Sie welche sehen, können Sie meine Fehler gerne korrigieren.
Evan Plaice
Informationen zur Unterstützung komplexer Zahlen finden Sie in der Antwort von @Matthew Wilcoxson. stackoverflow.com/a/3335060/290340 .
Evan Plaice
1
Die Verwendung von !anstelle von ist notmöglicherweise ein kleiner Fehler, aber Sie können dem floatin CPython integrierten Attribut definitiv keine Attribute zuweisen .
BlackJack
15

Für Zeichenfolgen von Nicht-Zahlen try: except:ist tatsächlich langsamer als reguläre Ausdrücke. Bei Zeichenfolgen mit gültigen Zahlen ist der reguläre Ausdruck langsamer. Die geeignete Methode hängt also von Ihrer Eingabe ab.

Wenn Sie feststellen, dass Sie sich in einer Leistungsbindung befinden, können Sie ein neues Drittanbieter-Modul namens Fastnumbers verwenden , das eine Funktion namens isfloat bereitstellt . Vollständige Offenlegung, ich bin der Autor. Ich habe seine Ergebnisse in die folgenden Zeitangaben aufgenommen.


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 du siehst

  • try: except: war schnell für numerische Eingaben, aber sehr langsam für ungültige Eingaben
  • Regex ist sehr effizient, wenn die Eingabe ungültig ist
  • fastnumbers gewinnt in beiden Fällen
SethMMorton
quelle
Ich stehe korrigiert da: -} es sah einfach nicht so aus, als würde es das tun. Vielleicht mit Namen wie prep_code_basisund prep_code_re_methodhätte meinen Fehler verhindert.
Alfe
Haben Sie etwas dagegen zu erklären, wie Ihr Modul funktioniert, zumindest für die isfloatFunktion?
Solomon Ucko
@SolomonUcko Hier ist ein Link zum Quellcode für den Teil zur Zeichenfolgenprüfung: github.com/SethMMorton/fastnumbers/blob/v1.0.0/src/… . Grundsätzlich geht es in der Reihenfolge über jedes Zeichen in der Zeichenfolge und überprüft, ob es einem Muster für einen gültigen Float folgt. Wenn die Eingabe bereits eine Zahl ist, wird nur der schnelle PyFloat_Check verwendet .
SethMMorton
1
Getestet gegen die besten Alternativen in diesem Thread bestätige ich, dass diese Lösung bei weitem die schnellste ist. Die zweitschnellste Methode str(s).strip('-').replace('.','',1).isdigit()ist ungefähr 10x langsamer!
Alexander McFarlane
14

Ich weiß, dass dies besonders alt ist, aber ich würde eine Antwort hinzufügen, von der ich glaube, dass sie die Informationen abdeckt, die in der Antwort mit der höchsten Abstimmung fehlen und die für jeden, der dies findet, sehr wertvoll sein könnte:

Verbinden Sie sie für jede der folgenden Methoden mit einer Zählung, wenn Sie eine Eingabe benötigen, die akzeptiert werden soll. (Angenommen, wir verwenden vokale Definitionen von ganzen Zahlen anstelle von 0-255 usw.)

x.isdigit() funktioniert gut, um zu überprüfen, ob x eine ganze Zahl ist.

x.replace('-','').isdigit() funktioniert gut, um zu überprüfen, ob x negativ ist. (Check - in erster Position)

x.replace('.','').isdigit() funktioniert gut, um zu überprüfen, ob x eine Dezimalzahl ist.

x.replace(':','').isdigit() funktioniert gut, um zu überprüfen, ob x ein Verhältnis ist.

x.replace('/','',1).isdigit() funktioniert gut, um zu überprüfen, ob x ein Bruch ist.

Aruthawolf
quelle
1
Obwohl für Brüche Sie wahrscheinlich etwas tun müssen x.replace('/','',1).isdigit()oder anderweitig Daten wie den 07.04.2017 als Zahlen falsch interpretiert würden.
Yuxuan Chen
Für die besten Möglichkeiten, die Bedingungen zu verketten
Daniel Braun
13

Diese Antwort enthält eine schrittweise Anleitung mit Beispielfunktionen zum Auffinden der Zeichenfolge:

  • Positive ganze Zahl
  • Positiv / Negativ - Ganzzahl / Float
  • Wie verwerfe ich "NaN" -Strings (keine Zahlen), während ich nach Zahlen suche?

Überprüfen Sie, ob die Zeichenfolge eine positive Ganzzahl ist

Sie können verwenden str.isdigit(), um zu überprüfen, ob die angegebene Zeichenfolge eine positive Ganzzahl ist.

Beispielergebnisse:

# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False

Überprüfen Sie, ob der String positiv / negativ ist - Ganzzahl / Gleitkomma

str.isdigit()Gibt zurück, Falsewenn die Zeichenfolge eine negative Zahl oder eine Gleitkommazahl ist. Zum Beispiel:

# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False

Wenn Sie auch nach negativen Ganzzahlenfloat suchen möchten, können Sie eine benutzerdefinierte Funktion schreiben, um Folgendes zu überprüfen:

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

Probelauf:

>>> 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

Verwerfen Sie "NaN" -Strings (keine Zahlen), während Sie nach Zahlen suchen

Die obigen Funktionen werden Truefür die Zeichenfolge "NAN" (keine Zahl) zurückgegeben, da es sich bei Python um einen gültigen Float handelt, der darstellt, dass es sich nicht um eine Zahl handelt. Zum Beispiel:

>>> is_number('NaN')
True

Um zu überprüfen, ob die Nummer "NaN" ist, können Sie Folgendes verwenden math.isnan():

>>> import math
>>> nan_num = float('nan')

>>> math.isnan(nan_num)
True

Wenn Sie keine zusätzliche Bibliothek importieren möchten, um dies zu überprüfen, können Sie sie einfach überprüfen, indem Sie sie mit sich selbst vergleichen ==. Python kehrt zurück, Falsewenn nanfloat mit sich selbst verglichen wird. Zum Beispiel:

# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False

Daher oben Funktion is_numberkann zurückkehren werden aktualisiert Falsefür"NaN" 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

Probelauf:

>>> 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 Prüfung in Abhängigkeit von der Art der Nummer bringt zusätzlichen Aufwand mit sich. Wählen Sie die is_numberFunktionsversion, die Ihren Anforderungen entspricht.

Moinuddin Quadri
quelle
12

Das Casting in Float und das Abfangen von ValueError ist wahrscheinlich der schnellste Weg, da float () genau dafür gedacht ist. Alles andere, was das Parsen von Zeichenfolgen erfordert (regulärer Ausdruck usw.), ist wahrscheinlich langsamer, da es nicht für diesen Vorgang optimiert ist. Meine $ 0,02.

codelogic
quelle
11
Ihre "2e-2"
-Dollar
8
@tzot Verwenden Sie NIEMALS einen Float, um einen Geldwert darzustellen.
Luke
6
@ Luke: Ich stimme Ihnen voll und ganz zu, obwohl ich nie vorgeschlagen habe, Floats zur Darstellung von Geldwerten zu verwenden. Ich habe nur gesagt , dass die Geldwerte können als Schwimmer :) dargestellt werden
tzot
11

Sie können Unicode-Zeichenfolgen verwenden. Sie haben eine Methode, um genau das zu tun, was Sie wollen:

>>> s = u"345"
>>> s.isnumeric()
True

Oder:

>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True

http://www.tutorialspoint.com/python/string_isnumeric.htm

http://docs.python.org/2/howto/unicode.html

Blackzafiro
quelle
2
für nicht negative Ints ist es ok ;-)
andilabs
1
s.isdecimal()prüft, ob die sZeichenfolge eine nicht negative Ganzzahl ist. s.isnumeric()Enthält Zeichen, die int()ablehnen.
JFS
9

Ich wollte sehen, welche Methode am schnellsten ist. Insgesamt lieferte die check_replaceFunktion die besten und beständigsten Ergebnisse . Die schnellsten Ergebnisse wurden von der check_exceptionFunktion erzielt , jedoch nur, wenn keine Ausnahme ausgelöst wurde. Dies bedeutet, dass der Code am effizientesten ist, der Aufwand für das Auslösen einer Ausnahme jedoch recht hoch ist.

Bitte beachten Sie, dass die Überprüfung auf eine erfolgreiche Besetzung die einzige Methode ist, die genau ist. Dies funktioniert beispielsweise, check_exceptionaber die beiden anderen Testfunktionen geben False für einen gültigen Float 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
Ron Reiter
quelle
10
Sie sollten die Leistung auch auf ungültige Fälle testen. Bei diesen Zahlen wird keine Ausnahme gemacht, was genau der "langsame" Teil ist.
Ugo Méda
1
@ UgoMéda ich nahm Ihren Rat von 2013 und tat es :)
Ron Reiter
"Bitte beachten Sie, dass die Überprüfung auf eine erfolgreiche Besetzung die einzige Methode ist, die genau ist" <- dies ist tatsächlich nicht wahr. Ich habe Ihren Test mit dem regulären Ausdruck in meiner obigen Antwort ausgeführt und er läuft tatsächlich schneller als der reguläre Ausdruck. Ich werde die Ergebnisse zu meiner obigen Antwort hinzufügen.
David Ljung Madison Stellar
Übrigens kann Ihr Ersteller von schlechten Zahlen als amüsanter Punkt tatsächlich einige legale Zahlen erstellen, obwohl dies ziemlich selten wäre. :)
David Ljung Madison Stellar
8

Wenn man also alles zusammenfasst und nach Nan, Unendlichkeit und komplexen Zahlen sucht (es scheint, dass sie mit j angegeben sind, nicht mit i, dh 1 + 2j), ergibt sich Folgendes:

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
a1an
quelle
Bisher die beste Antwort. Danke
anish
6

Die Eingabe kann wie folgt sein:

a="50" b=50 c=50.1 d="50.1"


1-Allgemeine Eingabe:

Die Eingabe dieser Funktion kann alles sein!

Findet, ob die angegebene Variable numerisch ist. Numerische Zeichenfolgen bestehen aus einem optionalen Vorzeichen, einer beliebigen Anzahl von Ziffern, einem optionalen Dezimalteil und einem optionalen Exponentialteil. Somit ist + 0123.45e6 ein gültiger numerischer Wert. Hexadezimale (zB 0xf4c3b00c) und binäre (zB 0b10100111001) Notationen sind nicht zulässig.

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

Prüfung:

>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True

is_float Funktion

Findet, ob die angegebene Variable float ist. float Strings bestehen aus optionalem Vorzeichen, beliebig vielen 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

Prüfung:

>>> 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 der Inhalt der Variablen String ist :

Verwenden Sie die Methode str.isdigit ()

>>> 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:

int-Wert erkennen:

>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>> 

Schwimmer erkennen:

>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True
Bastian
quelle
was ist " ast"?
4

Ich habe einen Geschwindigkeitstest gemacht. Nehmen wir an, wenn die Zeichenfolge wahrscheinlich eine Zahl ist, ist die Try / Except- Strategie die schnellstmögliche. Wenn die Zeichenfolge dies ist keine Zahl ist und Sie an einer Ganzzahlprüfung interessiert sind , lohnt es sich, einen Test durchzuführen (isdigit plus Überschrift) '-'). Wenn Sie die Float-Nummer überprüfen möchten , müssen Sie den Try / Except-Code ohne Escape verwenden.

FxIII
quelle
4

Ich musste feststellen, ob ein String in grundlegende Typen umgewandelt wurde (float, int, str, bool). Nachdem ich im Internet nichts gefunden habe, habe ich Folgendes erstellt:

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 den Typ erfassen und verwenden

s = "6.0"
type_ = str_to_type(s) # float
f = type_(s) 
Astrodsg
quelle
3

RyanN schlägt vor

Wenn Sie für NaN und Inf False zurückgeben möchten, ändern Sie die Zeile in x = float (s); return (x == x) und (x - 1! = x). Dies sollte True für alle Floats außer Inf und NaN zurückgeben

Dies funktioniert jedoch nicht ganz, da bei ausreichend großen Floats x-1 == xtrue zurückgegeben wird. Zum Beispiel,2.0**54 - 1 == 2.0**54

philh
quelle
3

Ich denke, Ihre Lösung ist in Ordnung, aber es gibt eine korrekte Regexp-Implementierung.

Es scheint eine Menge Regexp-Hass gegen diese Antworten zu geben, was ich für ungerechtfertigt halte. Regexps können einigermaßen sauber und korrekt und schnell sein. Es hängt wirklich davon ab, was Sie versuchen zu tun. Die ursprüngliche Frage war, wie Sie "überprüfen können, ob eine Zeichenfolge als Zahl (float) dargestellt werden kann" (gemäß Ihrem Titel). Vermutlich möchten Sie den numerischen / Gleitkommawert verwenden, sobald Sie überprüft haben, ob er gültig ist. In diesem Fall ist Ihr Versuch / Ihre Ausnahme sehr sinnvoll. Wenn Sie jedoch aus irgendeinem Grund nur überprüfen möchten, ob eine Zeichenfolge eine Zahl istdann funktioniert ein Regex auch gut, aber es ist schwer, richtig zu werden. Ich denke, die meisten bisherigen Regex-Antworten analysieren beispielsweise Strings nicht richtig ohne einen ganzzahligen Teil (wie ".7"), der für Python ein Float ist. Und das ist etwas schwierig in einem einzelnen regulären Ausdruck zu überprüfen, bei dem der Bruchteil nicht benötigt wird. Ich habe zwei Regex eingefügt, um dies zu zeigen.

Es wirft die interessante Frage auf, was eine "Zahl" ist. Fügen Sie "inf" hinzu, das als Float in Python gültig ist? Oder fügen Sie Zahlen hinzu, die "Zahlen" sind, aber möglicherweise nicht in Python dargestellt werden können (z. B. Zahlen, die größer als das Float-Maximum sind).

Es gibt auch Unklarheiten bei der Analyse von Zahlen. Was ist zum Beispiel mit "--20"? Ist das eine "Zahl"? Ist dies eine legale Art, "20" darzustellen? Mit Python können Sie "var = --20" ausführen und auf 20 setzen (obwohl dies wirklich darauf zurückzuführen ist, dass es als Ausdruck behandelt wird), aber float ("- 20") funktioniert nicht.

Wie auch immer, ohne weitere Informationen, hier ist ein regulärer Ausdruck, von dem ich glaube, dass er alle Ints abdeckt und schwebt, während Python sie analysiert .

# 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 Beispieltestwerte:

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

Das Ausführen des Benchmarking-Codes in der Antwort von @ ron-reiter zeigt, dass dieser reguläre Ausdruck tatsächlich schneller als der normale reguläre Ausdruck ist und schlechte Werte viel schneller verarbeitet als die Ausnahme, was sinnvoll ist. Ergebnisse:

check_regexp with good floats: 18.001921
check_regexp with bad floats: 17.861423
check_regexp with strings: 17.558862
check_correct_regexp with good floats: 11.04428
check_correct_regexp with bad floats: 8.71211
check_correct_regexp with strings: 8.144161
check_replace with good floats: 6.020597
check_replace with bad floats: 5.343049
check_replace with strings: 5.091642
check_exception with good floats: 5.201605
check_exception with bad floats: 23.921864
check_exception with strings: 23.755481
David Ljung Madison Stellar
quelle
Hoffe das stimmt - würde gerne von Gegenbeispielen hören. :)
David Ljung Madison Stellar
2
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
xin.chen
quelle
2
Denken Sie nicht daran 1e6, eine Zahl darzustellen?
Mark Dickinson
1

Hier ist meine einfache Art, es zu tun. Angenommen, ich durchlaufe einige Zeichenfolgen und möchte sie einem Array hinzufügen, wenn sich herausstellt, dass es sich um Zahlen handelt.

try:
    myvar.append( float(string_to_check) )
except:
    continue

Ersetzen Sie myvar.apppend durch eine beliebige Operation, die Sie mit der Zeichenfolge ausführen möchten, wenn sich herausstellt, dass es sich um eine Zahl handelt. Die Idee ist, zu versuchen, eine float () -Operation zu verwenden und den zurückgegebenen Fehler zu verwenden, um zu bestimmen, ob die Zeichenfolge eine Zahl ist oder nicht.


quelle
Sie sollten den Append-Teil dieser Funktion in eine else-Anweisung verschieben, um zu vermeiden, dass die Ausnahme versehentlich ausgelöst wird, falls mit dem Array etwas nicht stimmt.
DarwinSurvivor
1

Ich habe auch die von Ihnen erwähnte Funktion verwendet, aber bald stelle ich fest, dass Zeichenfolgen wie "Nan", "Inf" und ihre Variation als Zahl betrachtet werden. Daher schlage ich vor, dass Sie eine verbesserte Version Ihrer Funktion haben, die bei dieser Art von Eingabe false zurückgibt und "1e3" -Varianten nicht fehlschlägt:

def is_float(text):
    try:
        float(text)
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        return True
    except ValueError:
        return False
mathfac
quelle
1

Dieser Code behandelt die Exponenten, Gleitkommazahlen und Ganzzahlen ohne Verwendung von Regex.

return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False
Ravi Tanwar
quelle
1

Benutzerhilfefunktion:

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)])
Samantha Atkins
quelle
0

Sie können die Ausnahmetechnik auf nützliche Weise verallgemeinern, indem Sie nützlichere Werte als True und False zurückgeben. Diese Funktion setzt beispielsweise Anführungszeichen um runde Zeichenfolgen, lässt jedoch Zahlen in Ruhe. Welches ist genau das, was ich für einen schnellen und schmutzigen Filter brauchte, um einige Variablendefinitionen für R zu erstellen.

import 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:]), ')'
Thruston
quelle
0

Ich habe an einem Problem gearbeitet, das mich zu diesem Thread geführt hat, nämlich wie man eine Sammlung von Daten auf intuitivste Weise in Zeichenfolgen und Zahlen konvertiert. Nachdem ich den Originalcode gelesen hatte, stellte ich fest, dass das, was ich brauchte, in zweierlei Hinsicht anders war:

1 - Ich wollte ein ganzzahliges Ergebnis, wenn die Zeichenfolge eine Ganzzahl darstellt

2 - Ich wollte, dass eine Zahl oder ein String-Ergebnis in eine Datenstruktur passt

Also habe ich den Originalcode angepasst, um diese Ableitung 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
user1508746
quelle
0

Versuche dies.

 def is_number(var):
    try:
       if var == int(var):
            return True
    except Exception:
        return False
TheRedstoneLemon
quelle
is_number('10')
Kann
@geotheory, was meinst du mit "reagiert nicht"?
Solomon Ucko
0
def is_float(s):
    if s is None:
        return False

    if len(s) == 0:
        return False

    digits_count = 0
    dots_count = 0
    signs_count = 0

    for c in s:
        if '0' <= c <= '9':
            digits_count += 1
        elif c == '.':
            dots_count += 1
        elif c == '-' or c == '+':
            signs_count += 1
        else:
            return False

    if digits_count == 0:
        return False

    if dots_count > 1:
        return False

    if signs_count > 1:
        return False

    return True
Amir Saniyan
quelle