733 Stimmen

Wie kann ich überprüfen, ob eine Zeichenfolge eine int darstellt, ohne try/except zu verwenden?

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

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.

20voto

Bruno Bronosky Punkte 60135

Die richtige RegEx-Lösung würde die Ideen von Greg Hewgill und Nowell kombinieren, aber keine globale Variable verwenden. Sie können dies erreichen, indem Sie ein Attribut an die Methode anhängen. Ich weiß auch, dass es verpönt ist, Importe in eine Methode einzufügen, aber was ich anstrebe, ist ein "Lazy Module"-Effekt wie http://peak.telecommunity.com/DevCenter/Importing#lazy-imports

bearbeiten: Meine Lieblingstechnik ist bisher die ausschließliche Verwendung von Methoden des String-Objekts.

#!/usr/bin/env python

# Uses exclusively methods of the String object
def isInteger(i):
    i = str(i)
    return i=='0' or (i if i.find('..') > -1 else i.lstrip('-+').rstrip('0').rstrip('.')).isdigit()

# Uses re module for regex
def isIntegre(i):
    import re
    if not hasattr(isIntegre, '_re'):
        print("I compile only once. Remove this line when you are confident in that.")
        isIntegre._re = re.compile(r"[-+]?\d+(\.0*)?$")
    return isIntegre._re.match(str(i)) is not None

# When executed directly run Unit Tests
if __name__ == '__main__':
    for obj in [
                # integers
                0, 1, -1, 1.0, -1.0,
                '0', '0.','0.0', '1', '-1', '+1', '1.0', '-1.0', '+1.0',
                # non-integers
                1.1, -1.1, '1.1', '-1.1', '+1.1',
                '1.1.1', '1.1.0', '1.0.1', '1.0.0',
                '1.0.', '1..0', '1..',
                '0.0.', '0..0', '0..',
                'one', object(), (1,2,3), [1,2,3], {'one':'two'}
            ]:
        # Notice the integre uses 're' (intended to be humorous)
        integer = ('an integer' if isInteger(obj) else 'NOT an integer')
        integre = ('an integre' if isIntegre(obj) else 'NOT an integre')
        # Make strings look like strings in the output
        if isinstance(obj, str):
            obj = ("'%s'" % (obj,))
        print("%30s is %14s is %14s" % (obj, integer, integre))

Und für die weniger abenteuerlustigen Mitglieder der Klasse, hier ist das Ergebnis:

I compile only once. Remove this line when you are confident in that.
                             0 is     an integer is     an integre
                             1 is     an integer is     an integre
                            -1 is     an integer is     an integre
                           1.0 is     an integer is     an integre
                          -1.0 is     an integer is     an integre
                           '0' is     an integer is     an integre
                          '0.' is     an integer is     an integre
                         '0.0' is     an integer is     an integre
                           '1' is     an integer is     an integre
                          '-1' is     an integer is     an integre
                          '+1' is     an integer is     an integre
                         '1.0' is     an integer is     an integre
                        '-1.0' is     an integer is     an integre
                        '+1.0' is     an integer is     an integre
                           1.1 is NOT an integer is NOT an integre
                          -1.1 is NOT an integer is NOT an integre
                         '1.1' is NOT an integer is NOT an integre
                        '-1.1' is NOT an integer is NOT an integre
                        '+1.1' is NOT an integer is NOT an integre
                       '1.1.1' is NOT an integer is NOT an integre
                       '1.1.0' is NOT an integer is NOT an integre
                       '1.0.1' is NOT an integer is NOT an integre
                       '1.0.0' is NOT an integer is NOT an integre
                        '1.0.' is NOT an integer is NOT an integre
                        '1..0' is NOT an integer is NOT an integre
                         '1..' is NOT an integer is NOT an integre
                        '0.0.' is NOT an integer is NOT an integre
                        '0..0' is NOT an integer is NOT an integre
                         '0..' is NOT an integer is NOT an integre
                         'one' is NOT an integer is NOT an integre
<object object at 0x103b7d0a0> is NOT an integer is NOT an integre
                     (1, 2, 3) is NOT an integer is NOT an integre
                     [1, 2, 3] is NOT an integer is NOT an integre
                {'one': 'two'} is NOT an integer is NOT an integre

20voto

alkos333 Punkte 591
>>> "+7".lstrip("-+").isdigit()
True
>>> "-7".lstrip("-+").isdigit()
True
>>> "7".lstrip("-+").isdigit()
True
>>> "13.4".lstrip("-+").isdigit()
False

Ihre Funktion würde also lauten:

def is_int(val):
   return val.lstrip("-+").isdigit()

8voto

Grey2k Punkte 424

Der einfachste Weg, den ich benutze

def is_int(item: str) -> bool:
    return item.lstrip('-+').isdigit()

8voto

mRotten Punkte 427

Ich mache das ständig, weil ich eine leichte, aber zugegebenermaßen irrationale Abneigung gegen die Verwendung des Musters "versuchen/ausnehmen" habe. Ich verwende dies:

all([xi in '1234567890' for xi in x])

Negative Zahlen werden nicht berücksichtigt. Sie können also alle Minuszeichen auf der linken Seite entfernen und dann prüfen, ob das Ergebnis Ziffern von 0-9 enthält:

all([xi in '1234567890' for xi in x.lstrip('-')])

Sie können auch x an str() übergeben, wenn Sie nicht sicher sind, dass die Eingabe eine Zeichenkette ist:

all([xi in '1234567890' for xi in str(x).lstrip('-')])

Es gibt einige (Rand?)Fälle, in denen dies nicht funktioniert:

  1. Es funktioniert nicht für verschiedene wissenschaftliche und/oder exponentielle Schreibweisen (z.B. 1.2E3, 10^3, etc.) - beide geben False zurück. Ich glaube nicht, dass andere Antworten dies berücksichtigt haben, und selbst Python 3.8 hat widersprüchliche Meinungen, da type(1E2) gibt <class 'float'> während type(10^2) gibt <class 'int'> .
  2. Die Eingabe einer leeren Zeichenkette ergibt True.
  3. Ein führendes Pluszeichen (z. B. "+7") bedeutet Falsch.
  4. Mehrere Minuszeichen werden ignoriert, solange sie führende Zeichen sind. Dieses Verhalten ähnelt dem des Python-Interpreters*, da type(---1) gibt zurück. <class int> . Es ist jedoch nicht ganz konsistent mit dem Interpreter, da int('---1') gibt einen Fehler, aber meine Lösung liefert True mit der gleichen Eingabe.

Es wird also nicht funktionieren für jede mögliche Eingaben, aber wenn Sie diese ausschließen können, ist es eine gute einzeilige Prüfung, die folgende Ergebnisse liefert False wenn x keine ganze Zahl ist und True wenn x eine ganze Zahl ist. Aber wenn Sie wirklich ein Verhalten wünschen, das genau modelliert die int() eingebaut, sind Sie besser dran, wenn Sie try/except verwenden.

Ich weiß nicht, ob es pythonisch ist, aber es ist nur eine Zeile, und es ist relativ klar, was der Code tut.

*Ich will damit nicht sagen, dass der Interpreter führende Minuszeichen ignoriert, sondern nur, dass eine beliebige Anzahl von führenden Minuszeichen nichts daran ändert, dass das Ergebnis eine ganze Zahl ist. int(--1) wird tatsächlich interpretiert als -(-1) , oder 1. int(---1) wird interpretiert als -(-(-1)) oder -1. Eine gerade Anzahl von führenden Minuszeichen ergibt also eine positive ganze Zahl, eine ungerade Anzahl von Minuszeichen eine negative ganze Zahl, aber das Ergebnis ist immer eine ganze Zahl.

5voto

SuperNova Punkte 20412

Sie können die nachstehende Methode zur Überprüfung verwenden.

def check_if_string_is_int(string1):
    for character in string1:
        if not character.isdigit():
            return "Not a number"
    else:
        return "Is a number"

CodeJaeger.com

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.

Powered by:

X