Kann man irgendwie feststellen, ob ein String steht für eine ganze Zahl (z.B., '3'
, '-17'
aber nicht '3.14'
o 'asfasfas'
) Ohne Verwendung eines try/except-Mechanismus?
is_int('3.14') == False
is_int('-7') == True
Kann man irgendwie feststellen, ob ein String steht für eine ganze Zahl (z.B., '3'
, '-17'
aber nicht '3.14'
o 'asfasfas'
) Ohne Verwendung eines try/except-Mechanismus?
is_int('3.14') == False
is_int('-7') == True
Vorbedingungen:
int()
ist ein Standard für uns (manchmal ist es seltsam: "-00" ist die richtige Eingabe dafür)Kurze Antwort:
Verwenden Sie den folgenden Code. Er lautet einfach , richtig (während viele Varianten in diesem Thread es nicht sind) und fast übertrifft zweimal die Leistung beide try/except
y regex
Varianten.
def is_int_str(string):
return (
string.startswith(('-', '+')) and string[1:].isdigit()
) or string.isdigit()
TL;DR Antwort:
Ich habe 3 Hauptvarianten getestet (1) try/except, (2) re.match() und (3) String-Operationen (siehe oben). Die dritte Variante ist etwa doppelt so schnell wie beide try/except
y re.match()
. Übrigens: Die Regex-Variante ist am langsamsten! Siehe Testskript unten.
import re
import time
def test(func, test_suite):
for test_case in test_suite:
actual_result = func(*test_case[0])
expected_result = test_case[1]
assert (
actual_result == expected_result
), f'Expected: {expected_result} but actual: {actual_result}'
def perf(func, test_suite):
start = time.time()
for _ in range(0, 1_000_000):
test(func, test_suite)
return time.time() - start
def is_int_str_1(string):
try:
int(string)
return True
except ValueError:
return False
def is_int_str_2(string):
return re.match(r'^[\-+]?\d+$', string) is not None
def is_int_str_3(string):
return (
string.startswith(('-', '+')) and string[1:].isdigit()
) or string.isdigit()
# Behavior of built-in int() function is a standard for the following tests
test_suite = [
[['1'], True], # func('1') -> True
[['-1'], True],
[['+1'], True],
[['--1'], False],
[['++1'], False],
[['001'], True], # because int() can read it
[['-00'], True], # because of quite strange behavior of int()
[['-'], False],
[['abracadabra'], False],
[['57938759283475928347592347598357098458405834957984755200000000'], True],
]
time_span_1 = perf(is_int_str_1, test_suite)
time_span_2 = perf(is_int_str_2, test_suite)
time_span_3 = perf(is_int_str_3, test_suite)
print(f'{is_int_str_1.__name__}: {time_span_1} seconds')
print(f'{is_int_str_2.__name__}: {time_span_2} seconds')
print(f'{is_int_str_3.__name__}: {time_span_3} seconds')
Die Ausgabe war:
is_int_str_1: 4.314162969589233 seconds
is_int_str_2: 5.7216269969940186 seconds
is_int_str_3: 2.5828163623809814 seconds
Der Beitrag von Shavais hat mir sehr gut gefallen, aber ich habe noch einen weiteren Testfall hinzugefügt ( & die eingebaute Funktion isdigit()):
def isInt_loop(v):
v = str(v).strip()
# swapping '0123456789' for '9876543210' makes nominal difference (might have because '1' is toward the beginning of the string)
numbers = '0123456789'
for i in v:
if i not in numbers:
return False
return True
def isInt_Digit(v):
v = str(v).strip()
return v.isdigit()
und sie schlägt die Zeiten der anderen deutlich:
timings..
isInt_try: 0.4628
isInt_str: 0.3556
isInt_re: 0.4889
isInt_re2: 0.2726
isInt_loop: 0.1842
isInt_Digit: 0.1577
mit normalem 2.7er Python:
$ python --version
Python 2.7.10
Die beiden von mir hinzugefügten Testfälle (isInt_loop und isInt_digit) bestehen genau die gleichen Testfälle (beide akzeptieren nur ganze Zahlen ohne Vorzeichen), aber ich dachte, dass die Leute die String-Implementierung (isInt_loop) geschickter ändern könnten als die eingebaute isdigit()-Funktion, also habe ich sie mit einbezogen, obwohl es einen kleinen Unterschied in der Ausführungszeit gibt. (und beide Methoden schlagen alles andere um Längen, behandeln aber die zusätzlichen Dinge nicht: "./+/-" )
Außerdem fand ich es interessant festzustellen, dass der Regex (isInt_re2-Methode) den String-Vergleich im selben Test, der 2012 von Shavais durchgeführt wurde (aktuell 2018), geschlagen hat. Vielleicht sind die Regex-Bibliotheken verbessert worden?
Hier ist eine Funktion, die keine Fehler auslöst. Sie behandelt offensichtliche Fälle und gibt None
bei Fehlschlag (verarbeitet standardmäßig bis zu 2000 '-/+'-Zeichen in CPython!):
#!/usr/bin/env python
def get_int(number):
splits = number.split('.')
if len(splits) > 2:
# too many splits
return None
if len(splits) == 2 and splits[1]:
# handle decimal part recursively :-)
if get_int(splits[1]) != 0:
return None
int_part = splits[0].lstrip("+")
if int_part.startswith('-'):
# handle minus sign recursively :-)
return get_int(int_part[1:]) * -1
# successful 'and' returns last truth-y value (cast is always valid)
return int_part.isdigit() and int(int_part)
Einige Tests:
tests = ["0", "0.0", "0.1", "1", "1.1", "1.0", "-1", "-1.1", "-1.0", "-0", "--0", "---3", '.3', '--3.', "+13", "+-1.00", "--+123", "-0.000"]
for t in tests:
print "get_int(%s) = %s" % (t, get_int(str(t)))
Ergebnisse:
get_int(0) = 0
get_int(0.0) = 0
get_int(0.1) = None
get_int(1) = 1
get_int(1.1) = None
get_int(1.0) = 1
get_int(-1) = -1
get_int(-1.1) = None
get_int(-1.0) = -1
get_int(-0) = 0
get_int(--0) = 0
get_int(---3) = -3
get_int(.3) = None
get_int(--3.) = 3
get_int(+13) = 13
get_int(+-1.00) = -1
get_int(--+123) = 123
get_int(-0.000) = 0
Für Ihre Bedürfnisse können Sie verwenden:
def int_predicate(number):
return get_int(number) is not None
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
28 Stimmen
Warum versuchen beide, dies "auf die harte Tour" zu tun? Was ist falsch an try/except?
8 Stimmen
Ja, was ist falsch an try/except? Es ist besser, um Vergebung zu bitten als um Erlaubnis.
82 Stimmen
Ich würde fragen, warum sollte diese einfache Sache try/except erfordern? Das Ausnahmesystem ist ein komplexes Biest, aber dies ist ein einfaches Problem.
19 Stimmen
@Aivar hör auf, FUD zu verbreiten. Ein einzelner try/except-Block ist nicht einmal annähernd "komplex".
68 Stimmen
Es ist aber nicht wirklich FUD. Sie würden effektiv schreiben 4 Zeilen Code, erwarten, dass etwas zu explodieren, fangen, dass Ausnahme und tun Ihre Standard, anstatt mit einem Einzeiler.
2 Stimmen
Isinstance(deine_variable, basestring) sagt dir, ob die Variable entweder str oder unicode ist, oder beides. Dies beantwortet zwar nicht die spezifische Frage oben (mit der Umwandlung von String in eine Zahl), aber es beantwortet mindestens eine Frage, die als Duplikat zu dieser auf einer anderen Seite markiert ist, oder zumindest die Frage, die ich hatte, als ich diese Seite fand.
0 Stimmen
Hausaufgaben verbieten manchmal die Verwendung von try:. Wenn eine Ausnahme auftritt, selbst wenn Sie sie behandeln, wird sie erkannt und Sie bestehen die Aufgabe nicht.
4 Stimmen
@johnktejik Hier ist eine Idee - erstellen Sie einen Webservice, der die Frage beantwortet, ob eine Zeichenkette eine ganze Zahl sein kann, und stellen Sie dann im Code Ihrer Aufgabe eine HTTP-Anfrage an ihn. Der Webservice kann das try/catch ausführen
3 Stimmen
@dagrooms Ich liebe es. Ich frage mich, ob ihr Hacker-Alarm losgehen würde.
1 Stimmen
@S.Lott ich versuche dies in einem Listenverständnis zu tun also kein Versuch außer
2 Stimmen
Ausnahmen sind in Python üblich. Man kann nicht einmal eine
for
Schleife ohne Ausnahmebehandlung - einefor
Schleife stoppt, wenn der Iterator einStopIteration
Ausnahme. Die Website Entwurfsabsicht ist, dass Sie, wenn Sie wissen wollen, ob eine Zeichenkette als Ganzzahl interpretiert werden kann, die Funktionint
und fangen die Ausnahme ab.5 Stimmen
"Mach es auf die pythonische Art!", "Mach es auf die Microsoft-Art!", "Mach es auf die Google-Art!", "Mach es auf meine Art!". Wie wäre es mit Der Auftraggeber hat eine Frage gestellt, wie man etwas macht und die Bedingungen dafür genannt. Ich habe ein ähnliches Problem: Ich versuche herauszufinden, wie ich ein Element in einer Liste überprüfen kann, und die Übung sagt ausdrücklich, dass ich try/except nicht verwenden kann, und einige andere Einschränkungen, einschließlich einiger Einschränkungen hinsichtlich Leistung und Optimierung. Bis jetzt habe ich noch keine Lösung für diese Aufgabe gefunden.
2 Stimmen
@S.Lott Wenn Ausnahmen nicht außergewöhnlich sind, warum werden sie dann Ausnahmen genannt? Ausnahmen sollten für die Behandlung von Fehlern (und ich meine Fehler: Programmierfehler) sein. Ausnahmen sind der einzige Teil von Python, den ich nicht mag.
0 Stimmen
Ich denke, dass die Tatsache, dass OP nicht genau definiert, was ob eine Zeichenkette eine ganze Zahl darstellt hat zu einem Haufen unnötiger Verwirrung und Streitereien geführt.
1 Stimmen
Warum nicht try/except verwenden? Weil man sie nicht in einer Lambda-Funktion verwenden kann, wie man sie z.B. in
filter()
. Natürlich ist die Definition einer Nicht-Lambda-Funktion immer kurz und klar, so dass es keine große Sache ist, aber es ist gültig Frage.0 Stimmen
Was ist der Unterschied zu
s.isnumeric()
?