Rückgabewert "None" wird immer ausgegeben!

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
Random08
User
Beiträge: 1
Registriert: Samstag 13. August 2022, 13:07

Hallo,
Ich bin neu In der Python Programmierung und bin gerade dabei, ein Gewinnspiel als Übung in der Konsole zu Programmieren. Es wird aber immer, wenn ich "Nop1" ausgeben möchte, "None" zurückgegeben, obwohl ich eigentlich, den Input "Name_1_Participater" als rückgabewert bekommen sollte. Ihr könnt es ja mal Kopieren und Ausführen, vielleicht könnt ihr es dann auch besser nachvollziehen.

Ich hoffe um Hilfe, denn ich bin echt verzweifelt
Mfg Random08

Code: Alles auswählen

Name_1_Participater = input("Bitte geben Sie ihren Namen ein um am Gewinnspiel teilzunehmen: ")
def No_Input_Check(Nop):
    if Nop.isalnum():
        return Nop
    else:
        print(Nop)
        No_Input_Check(Nop=Nop)
Nop1 = No_Input_Check(Nop=Name_1_Participater)


def ste_te():
    global counter
    if counter == 1:
        ste = "ste"
        return ste
    elif counter > 1:
        te = "te"
        return te
te_ste = ste_te()

print(str(Nop1) + " hat bei diesem Gewinnspiel teilgenommen und ist der " + str(counter) + te_ste + " Teilnehmer!")
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Wieso glaubst du das alle Zweige überhaupt etwas zurückgeben?
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Namen werden in Python klein_mit_unterstrich geschrieben. Ausnahmen sind die Namen von Klassen (nicht deren Instanzen), die werden PascalCase geschrieben und Konstanten, die werden KOMPLETT_GROSS geschrieben.

Verwende vernünftige Namen. Buchstaben fressen kein Brot was soll denn ste_te sein? Das Geräusch eines nicht starteten Motors?
Namen sollen dem Leser des Codes (also auch dir) sagen, was er bedeutet.

Vergiss, dass es global gibt.
Man verwendet keine globalen Variablen. Alles was Funktionen für ihre Aufgabe benötigen, bekommen sie als Parameter und geben ihr Ergebnis mit return zurück.
Daraus ergibt sich, dass auf Modulebene (also uneingerückt) keine Variablen stehen.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Random08: Bei welchem Code oder welcher Eingabe passiert das was Du im Text beschreibst denn? In dem Code den Du gezeigt hast, bekomme ich entweder einen `RecursionError` oder einen `NameError`:

Code: Alles auswählen

$ python3.7 forum19.py
Bitte geben Sie ihren Namen ein um am Gewinnspiel teilzunehmen:

... (sehr viele Leerzeilen)

Traceback (most recent call last):
  File "forum19.py", line 8, in <module>
    Nop1 = No_Input_Check(Nop=Name_1_Participater)
  File "forum19.py", line 7, in No_Input_Check
    No_Input_Check(Nop=Nop)
  File "forum19.py", line 7, in No_Input_Check
    No_Input_Check(Nop=Nop)
  File "forum19.py", line 7, in No_Input_Check
    No_Input_Check(Nop=Nop)
  [Previous line repeated 992 more times]
  File "forum19.py", line 6, in No_Input_Check
    print(Nop)
RecursionError: maximum recursion depth exceeded while calling a Python object
$ python3.7 forum19.py 
Bitte geben Sie ihren Namen ein um am Gewinnspiel teilzunehmen: BlackJack
Traceback (most recent call last):
  File "forum19.py", line 19, in <module>
    te_ste = ste_te()
  File "forum19.py", line 13, in ste_te
    if counter == 1:
NameError: name 'counter' is not defined
Wenn Du ein Problem hast, dann zeige Bitte den Code der auch tatsächlich zur Problembeschreibung passt.

Anmerkungen zum tatsächlich gezeigten Code:

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Man nummeriert keine Namen. Dann will man sich entweder sinnvollere Namen überlegen, oder gar keine Einzelnamen/-werte, sondern eine Datenstruktur. Oft eine Liste. Beim gezeigten Quelltext sind die die 1en einfach nur überflüssig.

Ich würde auch dringend empfehlen nicht wie Yoda zu ”sprechen”. `name_participator` klingt komisch für einen Teilnehmernamen. Das wäre `participator_name`.

Man mischt Programm und Funktionsdefinitionen (oder Klassendefinitionen) nicht auf Modulebene. Das Hauptprogramm hat da nichts zu suchen, das steht üblicherweise in einer Funktion die `main()` heisst.

Man sollte Module importieren können, ohne das da mehr passiert als die Definition von Konstanten, Funktionen, und Klassen. Das bedeutet insbesondere auch keine globalen Variablen. Vergiss am besten gleich wieder, dass es das Schlüsselwort ``global`` überhaupt gibt. Funktionen und Methoden bekommen alles was sie ausser Konstanten benötigen, als Argument(e) übergeben.

Namen sollten keine kryptischen Abkürzungen enthalten und schon gar nicht nur daraus bestehen. Was `nop` als Argumentname bedeuten soll, ist mir auch nach angestrengtem Nachdenken nicht klar. Das Ergebnis einer Funktion die `ste_te()` heisst, an den Namen `te_ste` zu binden ist auch alles andere als selbsterklärend. Gute Namen sind wichtig. Die vermitteln dem Leser die Bedeutung des Wertes der dahinter steckt. Die sollten nicht zum rätselraten zwingen.

Wenn eine Funktion *ein* Argument entgegen nimmt, ist es in der Regel nicht sinnvoll das als Schlüsselwort-Argument zu übergeben. Falls das den Code wirklich verständlicher macht, was hier eindeutig nicht der Fall ist, sollte man überlegen ob der Funktionsname nicht besser sein könnte.

`nop1` müsste von der Bedeutung her eigentlich weiterhin `participator_name` heissen, denn das ist ja weiterhin der Name des Teilnehmers. Wobei hier auch `name` reichen würde, falls es nicht noch andere Namen im gleichen Kontext gibt, gegen die man diesen Namen abgrenzen müsste.

Die `no_input_check()`-Funktion ist kaputt, selbst wenn man das fehlende ``return`` ergänzt. Wenn der Benutzer etwas eingibt, was den ``if``-Test besteht, ist alles okay, aber im anderen Fall hat man eine sinnlose Endlosrekursion. Der rekursive Aufruf ist hier an sich schon falsch, weil selbst wenn da etwas sinnvolles getan würde, wäre das kein rekursives Problem was da gelöst wird, und Rekursion ist kein sinnvoller Ersatz für eine einfache Schleife. Zumindest nicht in Programmiersprachen die keine „tail call optimisation“ garantieren.

Man muss einen Rückgabewert nicht eine Zeile vor dem ``return`` an einen Namen binden. insbesondere wenn das sowieso nur eine literale Zeichenkette ist, macht das überhaupt gar keinen Sinn.

In `ste_te()` wird entweder "te" oder "ste" oder `None` zurückgegeben. Letzteres *implizit* weil der Fall im Code einfach nicht berücksichtigt wird. So etwas sollte man nicht machen. An der Stelle sollte man entweder *explizit* `None` zurückgeben, oder eine Ausnahme auslösen, oder diesen Fall anders sinvoll behandeln.

Das zusammenstückeln von Zeichenketten und Werten mittels ``+`` und `str()` ist eher BASIC als Python. Dafür gibt es die `format()`-Methode auf Zeichenketten und f-Zeichenkettenliterale. Beziehungsweise kann man beim `print()` auch nutzen, dass dort mehrere Argumente angegeben werden können, die von `print()` dann in Zeichenketten umgewandelt und mit Leerzeichen getrennt ausgegeben werden.

Überarbeitet, aber immer noch mit den gleichen Problemen/Ausnahmen wie das Original:

Code: Alles auswählen

#!/usr/bin/env python3


def no_input_check(text):
    if text.isalnum():
        return text
    else:
        print(text)
        return no_input_check(text)


def function_in_a_need_for_a_better_name(counter):
    if counter == 1:
        return "ste"

    if counter > 1:
        return "te"

    raise ValueError(f"expected counter value in 1.., got {counter}")


def main():
    name = no_input_check(
        input(
            "Bitte geben Sie ihren Namen ein um am Gewinnspiel teilzunehmen: "
        )
    )
    need_a_better_name_here = function_in_a_need_for_a_better_name(counter)
    print(
        f"{name} hat bei diesem Gewinnspiel teilgenommen und ist der"
        f" {counter}{need_a_better_name_here} Teilnehmer"
    )


if __name__ == "__main__":
    main()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Benutze keine kryptischen Abkürzung. Was ist ein nop? Oder ein ste_te?
Programmcode sollte nicht zum Rätseln da sein.
Variablennamen und Funktionen schreibt man komplett klein.
No_Input_Check hat für mich eine Endlosrekursion.
Vergiss gleich wieder dass es so etwas wie `global` überhaupt gibt. Das hat in einem sauberen Programm nichts verloren.
Man muß nicht alles an Variablen binden:

Code: Alles auswählen

def to_cardinal(number):
    if number == 1:
        return "1ste"
    return f"{number}te"
 print(f"{name_of_participant} hat bei diesem Gewinnspiel teilgenommen und ist der {to_cardinal(counter)} Teilnehmer!")
Antworten