Seite 2 von 3

Verfasst: Freitag 17. Juli 2009, 20:10
von problembär
Glückwunsch, Du hast das von mir oben schon erwähnte

Code: Alles auswählen

str.isdigit()
neu implementiert!

Verfasst: Freitag 17. Juli 2009, 20:27
von cofi
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 ;)

Verfasst: Sonntag 19. Juli 2009, 12:30
von AntagonisT
@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.

Verfasst: Sonntag 19. Juli 2009, 12:43
von HerrHagen
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

Verfasst: Sonntag 19. Juli 2009, 14:02
von 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')

Verfasst: Sonntag 19. Juli 2009, 16:24
von 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

Verfasst: Sonntag 19. Juli 2009, 20:09
von DasIch
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

Verfasst: Sonntag 19. Juli 2009, 21:53
von 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ß

Verfasst: Sonntag 19. Juli 2009, 22:05
von derdon

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.

Verfasst: Sonntag 19. Juli 2009, 22:37
von 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()

Verfasst: Sonntag 19. Juli 2009, 23:30
von EyDu
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

Verfasst: Dienstag 21. Juli 2009, 18:05
von birkenfeld
Inzwischen wird es wirklich einfacher, ``int()`` direkt aufzurufen.

Verfasst: Dienstag 21. Juli 2009, 20:46
von problembär
Stimmt leider.

Verfasst: Mittwoch 22. Juli 2009, 17:23
von 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

Verfasst: Mittwoch 22. Juli 2009, 17:27
von DasIch
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?

Verfasst: Mittwoch 22. Juli 2009, 17:29
von 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.

Verfasst: Mittwoch 22. Juli 2009, 17:31
von DasIch
Zwischen eval, und int/float/complex besteht allerdings ein kleiner Unterschied.

Verfasst: Mittwoch 22. Juli 2009, 18:47
von EyDu
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.

Verfasst: Mittwoch 22. Juli 2009, 19:44
von 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

Verfasst: Mittwoch 22. Juli 2009, 20:39
von birkenfeld
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.