Anfängerproblem bei Usereingaben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
problembär

Glückwunsch, Du hast das von mir oben schon erwähnte

Code: Alles auswählen

str.isdigit()
neu implementiert!
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nicht wirklich ;)
Aber das Stueck Code ist trotzdem eher nicht zu gebrauchen. Warum? Du vermischst die Ueberprufung auf ``int`` mit einem erneuten Prompt. Wenn du schon so eine Funktion haben willst, hier mein Vorschlag:

Code: Alles auswählen

def int_input(prompt="Gimme an Integer! "):
	try:
		return int(input(prompt)
	except ValueError:
		print("I said Integer!")
		return int_input()
Edit: Es ist zwar lobenswert, dass du einen Test schreibst, aber auch dort sollte man der Maxime folgen, dass Code lesbar ist ;)
AntagonisT
User
Beiträge: 42
Registriert: Samstag 11. Juli 2009, 16:36

@Problembär:

Danke :wink: Ich versuche erstmal, Python zu lernen und ich habe bei der Umsetzung mehr gelernt, als wenn ich nur "einfach" ein fertiges Modul genommen hätte. Ihr Profis macht das natürlich anders.

@Rest:

habe den code noch mal vereinfacht und (hoffentlich) verbessert:

Code: Alles auswählen

# überprüft, ob Nutzereingaben den Typen "int"
# oder "float" entsprechen


# überprüft auf Typ "integer" und gibt wert zurück
def int_check (string):
    fehler = 1
    while fehler == 1:
        wert = input (string)
        try:
            wert = int (wert)
            fehler = 0
            return wert
        except:
            print ("FEHLER: erwartet Ganzzahl")
            print ("")


# überprüft auf Typ "float" und gibt wert zurück
# Trennzeichen Komma "," wird  in Punkt "." umgewandelt!
def float_check (string):
    fehler = 1
    while fehler == 1:
        wert = input (string)
        try:
            wert = wert.replace (",", ".")
            wert = float (wert)
            fehler = 0
            return wert
        except:
            print ("FEHLER: erwartet Gleitkommazahl")
            print ("")
aufgerufen wird das Ganze jetzt einfach mit

Code: Alles auswählen

import input_check

x = input_check.int_check ("bitte eine ganze Zahl eingeben: ")
y = input_check.float_check ("bitte eine Gleitkommazahl eingeben: ")
es gibt jetzt nur noch ein einziges "input" im Code und es wird nur ein einziger Parameter übergeben.
Zuletzt geändert von AntagonisT am Sonntag 19. Juli 2009, 12:46, insgesamt 1-mal geändert.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

problembär hat geschrieben:Zeig' doch bitte mal ein Beispiel, in dem das mit dem Konstrukt, das ich genannt habe, nicht funktioniert.
Besonders bei der Arbeit mit numpy führt kein Weg an isinstance vorbei:

Code: Alles auswählen

>>> import numpy
>>> x = numpy.arange(10).sum()
>>> x
45
>>> type(x)
<type 'numpy.int32'>
>>> type(x) == int
False
>>> isinstance(x, int)
True
MFG HerrHagen
BlackJack

@AntagonisT: Die Namen der Funktionen sind nicht so passend, denn es geht ja nicht um das überprüfen, sondern um die Einfabe plus Überprüfung. Und die beiden Funktionen sehen *sehr* ähnlich aus, ein Zeichen, dass man da etwas zusammenfassen kann.

Für Wahrhaitswerte gibt es `True` und `False` statt 1 und 0, wobei `fehler` in beiden Fällen irrelevant ist, da es immer 1 ist, ausser ganz kurz vor dem ``return``. Da ist das aber egal, da das ``return`` die Funktion in jedem Fall beendet. Ungetestet und für Python 2.5+:

Code: Alles auswählen

from functools import partial


def checked_input(convert_func, error_message, prompt):
    while True:
        try:
            return convert_func(raw_input(prompt))
        except Exception, error:
            print error_message, error
            print


def float_convert(string):
    return float(string.replace(',', '.'))


int_input = partial(checked_input, int, 'Expected integer')

float_input = partial(checked_input, float_convert, 'Expected floating point')
problembär

@DasIch, HerrHagen, birkenfeld: Ok, numpy und Vererbung sind beides Sachen, die ich selten verwende.
Trotzdem überzeugt mich das. Wenn man isinstance() schonmal hat, kann man's ja auch ruhig verwenden ...

Viele Grüße
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

problembär hat geschrieben:Glückwunsch, Du hast das von mir oben schon erwähnte

Code: Alles auswählen

str.isdigit()
neu implementiert!
Damit kann man nicht prüfen ob eine Zahl ein integer ist.

Code: Alles auswählen

>> "-1".isdigit()
 > False
>> int("-1")
 > -1
problembär

Sehr spitzfindig ... so besser ?

Code: Alles auswählen

def isint(s):
    if s.isdigit() or len(s) > 1 and s[0] == "-" and s[1:].isdigit():
        return True
    else:
        return False

print isint("-1234")
Gruß
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Code: Alles auswählen

def isint(s):
    return s.isdigit() or len(s) > 1 and s[0] == "-" and s[1:].isdigit()

# oder als lambda:
# isint = lambda s: s.isdigit() or len(s) > 1 and s[0] == "-" and s[1:].isdigit()

print isint("-1234")
macht genau das gleiche.
BlackJack

Hach ja, irgendwas übersieht man ja immer:

Code: Alles auswählen

In [25]: isint('+1')
Out[25]: False

In [26]: int('+1')
Out[26]: 1
:-)

Wobei man `isint()` auch noch ein bisschen kürzen kann:

Code: Alles auswählen

def isint(s):
    return s[s.startswith('-'):].isdigit()
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Bei so etwas einfachen kann man auch offensichtlich keine Fehler machen.

Code: Alles auswählen

>>> isint("- 1")
False
>>> int("- 1")
-1
>>> isint(" -1")
False
>>> int(" -1")
-1
>>> isint(" 1")
False
>>> int(" 1")
1
Das Leben ist wie ein Tennisball.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Inzwischen wird es wirklich einfacher, ``int()`` direkt aufzurufen.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
problembär

Hallo nochmal,

hab' noch einmal drüber nachgedacht. Wie oben schon gesagt, müßte man am besten wohl einen regulären Ausdruck nehmen. In sowas sind ja die Perl-Leute Spezialisten, und sie haben sich auch damit befaßt, sogar mehrfach.

Das Ergebnis war aber immer noch nicht so, wie ich's wollte, deshalb hab' ich auch noch einen eigenen regulären Ausdruck (für float) geschrieben (der aber nicht diese "3E+23"-Sachen erkennt):

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import re

a = ('','foo 30','.20','20.',',20','20,','1.3E2', '2..3','++3','2.3.',
     '10','..3','0','100','100.23','1,100.23','-3E-2', "- 15.3", " 24.32   ",    "+ 32. ",         " - 21,23 ", "-.", "-")

patobj = re.compile("^ *[+-]? *(\d+|\d+\.\d*|\d*\.\d+) *$")

for i in a:

    if patobj.search(i):
        print i + " is True."
    else:
        print i + " is False."

    try:
        b = float(i)
        print i + " is Good."
    except:
        print i + " is Bad."
    print
Bestimmt entdeckt ihr jetzt wieder noch ein paar Schwächen.

Ist wohl ein bekanntes, aber gar nicht so einfaches Problem.

Viele Grüße
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

problembär hat geschrieben:Wie oben schon gesagt, müßte man am besten wohl einen regulären Ausdruck nehmen.
Wieso auch einfach wenn es auch kompliziert und unvollständig geht?
problembär

Weil zumindest in Perl:
>>USe an eval, it's correct (by definition) and avoids possible errors
>QA Editors note: This solution doesn't work as described.
Außerdem lasse ich meine Anwendung sich wenn möglich nicht vorsätzlich aufhängen (try: ... except: ....), vor allem wenn ich meinen Code auch mal in andere Sprachen bringen will, die das nicht unterstützen.
Zuletzt geändert von problembär am Mittwoch 22. Juli 2009, 17:31, insgesamt 1-mal geändert.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Zwischen eval, und int/float/complex besteht allerdings ein kleiner Unterschied.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

problembär hat geschrieben:Außerdem lasse ich meine Anwendung sich wenn möglich nicht vorsätzlich aufhängen (try: ... except: ....), vor allem wenn ich meinen Code auch mal in andere Sprachen bringen will, die das nicht unterstützen.
try-except ist bei Python allerdings vollkommen üblich und sogar ausdrücklich erwünscht (Stichwort: EAFP).

Das Umwandeln in eine andere Sprache ist ein wirklich sinnloses Argument. Jede Sprache hat ihre Eigenheiten und Paradigmen, welche auch beachtet werden sollten. Einfach kopieren macht keinen Sinn. Mit deinem Ansatz provozierst du zusätzlich noch Fehler. Zu schlechtem Code kommt dann noch ein fehlerhaftes Programm.
Das Leben ist wie ein Tennisball.
problembär

und unvollständig
Ist soweit nicht unvollständig. Bei den Leerzeichen war ich nur etwas großzügig. Das heißt, vor der Umwandlung in float muß man noch die Leerzeichen rausziehen:

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import re

a = ('','foo 30','.20','20.',',20','20,','1.3E2', '2..3','++3','2.3.',
     '10','..3','0','100','100.23','1,100.23','-3E-2', "- 15.3", " 24.32   ",    "+ 32. ",         " - 21,23 ", "-.", "-")

patobj = re.compile("^ *[+-]? *(\d+|\d+\.\d*|\d*\.\d+) *$")

for i in a:

    if patobj.search(i):
        print i + " is True."
        i = i.replace(" ", "")
        i = float(i)
        print "Type of i is now: " + str(type(i))
    else:
        print i + " is False."
    print
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Trotzdem ist dein Code immer noch unvollständig, was z.B. 1e5 angeht.

Es ist ganz falsch, das potentielle Auslösen einer Exception als "aufhängen" zu bezeichnen. Exceptions sind eigentlich in allen Sprachen, die sie unterstützen, und in Python ganz besonders eben nicht so "außergewöhnlich", wie der Name vermuten ließe. Sie sind ein Sprachelement wie jedes andere, und werden z.B. auch ganz regulär verwendet, um das Ende eines Iterators zu signalisieren - jede "for"-Schleife, die du verwendest, verarbeitet Exceptions.

Zu den anderen Sprachen hat EyDu schon alles gesagt.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Antworten