Funktion die eingegebene Dezimalzahlen zählt

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.
Antworten
lukdill
User
Beiträge: 4
Registriert: Mittwoch 20. Oktober 2021, 18:08

Guten Abend allerseits,

ich bin noch ein ziemlicher Anfänger was Python angeht und habe mir zum reinstarten ein Buch zum Schnelleinstieg ausgeliehen.
In dem Buch sind am Ende der Kapitel immer Aufgaben zum selber machen und so auch diese: "Schreibe eine Funktion, die einen eingegeben Text als Argument übernimmt und die Dezimalzahlen zählt die darin vorkommen."
Ich habe es schon mehrmals versucht, aber es will nicht so recht klappen. Hier erstmal das, was ich bisher habe:

def ziffern():
y = 0
i = ["0","1","2","3","4","5","6","7","8","9"]
for i in x:
y += 1
return y

x = input("Text: ")
b = ziffern()

print("Im Text sind ", b, "Dezimalzahlen")

Kann mir jemand sagen, warum das so nicht funktioniert und was ich verbessern könnte, sodass es klappt?

Danke für eure Antworten im Voraus und noch einen schönen Abend!
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Alles was eine Funktion braucht, muß sie über ihre Argumente bekommen. Variablennamen müssen sprechend sein, damit man den Code verstehen kann.
Du hast i für zwei verschiedene Dinge benutzt, das wäre nicht passiert, wenn man gute Namen wählt:

Code: Alles auswählen

def zaehle_ziffern(text):
    anzahl = 0
    ziffern = ["0","1","2","3","4","5","6","7","8","9"]
    for zeichen in text:
        anzahl += 1
    return anzahl


def main():
    text = input("Text: ")
    anzahl = zaehle_ziffern(text)
    print(f"Im Text sind {anzahl} Dezimalzahlen")

if __name__ == "__main__":
    main()
Weder mit zeichen noch mit ziffern wird etwas gemacht, die wesentliche Funktionalität fehlt also in der Funktion.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei ich die Aufgabenstellung sehr schwammig bis schlecht finde. Was sind denn in diesem Kontext Dezimalzahlen? Tatsächlich einzelne Dezimalziffern? Das sind ja normalerweise eben nur das: Ziffern. Aus denen Dezimalzahlen zusammengesetzt sind. Also ist das Ergebnis bei "42 und 23" jetzt 4 (Ziffern) oder 2 (Dezimalzahlen)? Und wie sieht das aus, wenn diese Zahlen nicht frei stehen? Und damit vielleicht auch Teil von Zahlen mit anderen Basen sind?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
lukdill
User
Beiträge: 4
Registriert: Mittwoch 20. Oktober 2021, 18:08

Hallo Sirius3,

danke sehr für deine Antwort!
Leider ist es so, dass dein Code genau das gleiche macht wie mein Code, d.h. er zählt ALLE Zeichen die im Text vorkommen, unabhängig davon, ob es Ziffern oder Buchstaben sind. Die Aufgabe war ja, dass alle Ziffern gezählt werden. Hättest du trotzdem eine Idee, wie ich das hinbekommen könnte?
Und ich habe noch zwei Fragen: 1. Wieso hast du in der print Funktion ein f davor gestellt, ich habe bereits bemerkt, dass es nur mit diesem f eine gscheite Ausgabe gibt, aber ich verstehe nicht woher dieses f herkommt.
2. Die If Anweisung verstehe ich überhaupt nicht. Was genau machst du da? Was bedeuten die Unterstriche?
Das mit den sprechenden Variablen werde ich in Zukunft beachten, danke für den Hinweis.

Schönen Nachmittag noch :)
lukdill
User
Beiträge: 4
Registriert: Mittwoch 20. Oktober 2021, 18:08

Zur Aufgabenstellung, ich denk ich bin da selbst schuld, ich hab das etwas schlecht beschrieben. Es geht tatsächlich um die einzelnen Ziffern. Wenn jetzt "42" eingegeben würde, sollte die Ausgabe also 2 sei.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Der Code macht genau das selbe wie Deiner, er sollte nur zeigen, dass es viel lesbarer ist, mit guten Variablennamen.
Das f ist ein Formatstring und benutzt man immer, wenn man Text formatieren will.
Zum Problem: an welcher Stelle wird die Anzahl gezählt und wann soll gezählt werden? Wie prüft man also, ob das zeichen eine ziffer ist?
lukdill
User
Beiträge: 4
Registriert: Mittwoch 20. Oktober 2021, 18:08

Hallo,

ich habe jetzt eine Lösung gefunden und einen Code der funktioniert:

Code: Alles auswählen

def zähle_ziffern(text=input("Text: ")):

    alle_zahlen = 0
    if "1" or "2" or "3" or "4" or "5" or"6" or"7" or "8" or "9" in text:
            zahlen = [ text.count('0'),
            text.count('1'),
            text.count('2'),
            text.count('3'),
            text.count('4'),
            text.count('5'),
            text.count('6'),
            text.count('7'),
            text.count('8'),
            text.count('9')]
            alle_zahlen = sum(zahlen)

    return alle_zahlen
   

anzahl_ziffern = zähle_ziffern()

print("Im Text sind ", anzahl_ziffern, "Dezimalzahlen")
Ist jetzt nicht gerade eine elegante Lösung, aber es funktioniert. Wie könnte man das mit dem Zählen eleganter/schneller machen?

Danke im Voraus!
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das macht nicht das, was du denkst das es tut. Dein ganzer or-Ausdruck ist IMMER wahr, egal wis in text ist. Denn du denkst, das wuerde bedeuten "wenn einer der Zahlen hier vorne in text ist". Bedeutet es aber nicht. Stattdessen ist schon "1" wahr (weil alle Strings, die nicht der Leerstring sind, wahr ausgewertet werden), und das ganze Ding ist immer wahr. Das if kannst du dir also sparen.

Dann ist deine Entscheidung, intput("Text") als default-Argument einzufuehren, abenteuerlich. Denn das passiert dann nur einmal, wenn die Funktion das erste mal vom Interpreter geparst wird. Und nicht, wie du denkst, wenn sie aufgerufen wird. Kannst du dich ganz einfach selbst von ueberzeugen: loesch einfach mal den Aufruf von zaehle_ziffern unten im Code, und trotzdem wird das abgefragt. Das muss also ganz dringend da raus, und als Zeile *vor* den Aufruf, und dann eben als Argument an zaehle_ziffern uebergeben werden. Wie es dir hier auch schon vorgemacht wurde.

Zu guter Letzt wuerde ich das eigentliche Zaehlen nicht 10 mal hinschreiben. Sondern eine Schleife, welche die Zahlen 0-9 erzeugt, und dann nach denen im Text suchen, mit count.

Code: Alles auswählen

all_digits = sum(text.count(str(digit)) for digit in range(10))
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Das ist wirklich sehr umständlich. Eine kompakte Variante deines ursprünglichen Ansatzes könnte so aussehen:

Code: Alles auswählen

In [9]: DIGITS = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
   ...: def count_digits(text):
   ...:     result = 0
   ...:     for char in text:
   ...:         if char in DIGITS:
   ...:             result += 1
   ...:     return result
   In [10]: count_digits('23 und 42')
Out[10]: 4
Aber eigentlich musst du gar nicht die Zahlen alle hinschreiben, sonst könntest z. B. auch die isdigit-Methode verwenden:

Code: Alles auswählen

In [11]: def count_digits(text):
    ...:     result = 0
    ...:     for char in text:
    ...:         if char.isdigit():
    ...:             result += 1
    ...:     return result
    ...: 
    ...: 
    ...: 

In [12]: count_digits('23 und 42')
Out[12]: 4
Und da du ja schon selbst sum verwendest hattest, kann man vielleicht auch noch eine fortgeschrittene Variante zeigen:

Code: Alles auswählen

In [13]: def count_digits(text):
    ...:     return sum(1 for char in text if char.isdigit())
    ...: 

In [14]: count_digits('23 und 42')
Out[14]: 4
(Man kann auch das char.isdigit() nach vorne stellen und ausnutzen, dass boolsche Werte einen Integer-Wert haben, dann wird es noch kürzer. Persönlich finde ich diesen Trick aber nicht so lesbar.)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@nezzcarth: und da True 1 ist und False 0 ist die Summe einfach:

Code: Alles auswählen

def count_digits(text):
    return sum(char.isdigit() for char in text)
isdigit liefert True für viele verschiedene Ziffern-Zeichen.
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

@Sirius3: Ja, ich weiß, und hatte schon befürchtet, dass das jemand noch anspricht; daher hatte ich es noch rein-editiert, nachdem du es vmtl. gesehen hast. Meiner Meinung nach ist das jedoch eher ein Trick, den ich persönlich nicht verwenden würde.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Noch mal zu dem falschen `isdigit()`: Es gibt da auf Zeichenketten auch eine Methode die das richtige macht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
DeaD_EyE
User
Beiträge: 1017
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Code: Alles auswählen

from string import digits


DIGITS = frozenset(digits)
# schneller beim lookup
# 0 - 9


def count_digits(text):
    return sum(char in DIGITS for char in text)
Die Zeichen sind auf 0-9 begrenzt und nicht die vollständige Gruppe decimal aus dem Unicode-Bereich.

Beispiel:

Code: Alles auswählen

print(int("߁߃߃߇"))
1337

Man kann damit ein wenig spielen und lernen.

Code: Alles auswählen

import unicodedata


leet1 = "①③③⑦"
leet2 = "߁߃߃߇"

if leet1.isdecimal():
    print("leet1 is decimal")

if leet1.isnumeric():
    print("leet1 is numeric")

if leet2.isdecimal():
    print("leet2 is decimal")

if leet2.isnumeric():
    print("leet2 is numeric")


# da leet1 nur in der Gruppe numeric ist, kann es mit int nicht direkt umgewandelt werden
decimal_str = unicodedata.normalize("NFKC", leet1)
value = int(decimal_str)

# und wenn die Zeichen zur Gruppe decimal gehören, geht auch:
value2 = int(leet2)
Hier gibt es eine Übersicht, falls es jemanden interessiert: https://www.fileformat.info/info/unicod ... d/list.htm
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten