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.

War es hilfreich?

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

 image description hier

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

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

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

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.

machen
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:]), ')'

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')
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top