Einfaches Python-Konsolenspiel mit ineffizientem Codefluss

Oct 07 2020

Ich habe ein einfaches Programm als Übung zur Verbesserung meines Codeflusses in Python erstellt, das Folgendes bewirkt:

  1. fordert den Benutzer auf, seinen Namen einzugeben
  2. bietet ihnen die Wahl, entweder ihren Namen in umgekehrter Reihenfolge oder die Anzahl der Zeichen zu drucken
  3. Nachdem die Ausgabe gedruckt wurde, wird der Benutzer gefragt, ob er "erneut spielen" möchte. Wenn nicht, wird beendet

Habe ich etwas besonders doof gemacht? Irgendwelche niedrig hängenden Früchte? Best Practice, die mir nicht bekannt ist?

from sys import exit

def userinput():
    print('Enter your name:')
    n = input()
    print('Hello, ' + n + ', would you rather (R)everse or (C)ount the letters of your name?')
    a = input()
    return (a,n)

def choosef(choice,myname):
    while choice not in ['R','C']:
        print("Only 'R' or 'C' are valid. Try again:")
        choice = input()
    if choice == 'R':
        print(''.join(reversed(myname)))
    else:
        spaces = 0
        for c in list(myname):
            if c == ' ':
                spaces = spaces + 1
        print('Total # Characters: ' + str(len(myname) - spaces))
    playagain()

def playagain():
    print("Would you like to play again, (Y)es or any other character to exit?")
    yn = input()
    if yn == 'Y':
        ui = userinput()
        choosef(ui[0],ui[1])
    else:
        exit()

ui = userinput()
choosef(ui[0],ui[1])

Antworten

31 AryanParekh Oct 07 2020 at 10:55

Versuchen Sie, alles zu vergessen, was Sie über den Code wissen, und nehmen Sie an, dass Sie nicht der Autor sind. Stellen Sie sich vor, Sie sind eine dritte Person, die den Code liest, nichts darüber weiß und ihn nur zum ersten Mal liest.

ui = userinput()
choosef(ui[0],ui[1])

Okay, userinput()ich muss etwas eingeben und hineinstecken ui. Sinnvoll, aber was ist choosef()?

Namenskonvention

Verwenden Sie aussagekräftige Namen für Funktionen und Variablen. Nehmen Sie dieses Beispiel

x = 3.14
y = 24

Was ist xund yfür den Leser? Ist das der Preis von etwas?

pi_value = 3.14
number_of_hours = 24

Ahhh okay, jetzt weiß ich genau was 3.14bedeutet. Wenn ich es also irgendwo benutze, weiß der Leser auch, was ich genau meine. Dies ist ein wichtiger Teil beim Schreiben von sauberem Code.

Ein weiterer Aspekt ist der Stil. Es gibt einige Möglichkeiten, wie ich Benutzereingaben schreiben kann *

user_input()
USERINPUT()
UserInput()
userinput()

Welchem ​​soll ich folgen?

Um eine konsistente Namenskonvention zu erhalten, folgt der Python-Code der PEP-8- Namenskonvention. Wenn ich Folgendes sage, meine ich, dass es empfohlen wird, dass Sie es auch befolgen, da andere Python-Bibliotheken dies ebenfalls verwenden. Dadurch sieht der Code sauberer aus.

Dinge wie Funktionen folgen: lower_snake_case

Klassen folgen: CamelCase

Sie können den Link für weitere Informationen lesen.

Eingaben in Python

print('Enter your name:')
n = input()

Natürlich möchten Sie dem Benutzer eine Nachricht anzeigen, bevor er etwas eingibt. Aus diesem Grund verfügt die input()Funktion über eine sogenannte Eingabeaufforderung .

name = input("Enter your name: ")

Sie können die Nachricht zwischen dem anzeigen (). Dadurch wird die zusätzliche Zeile entfernt. Beachten Sie auch , dass ich geändert , num nameaus den Gründen , die ich oben erwähnt.

Zeichenfolgen formatieren

Aus Ihrem Code kann ich ersehen, dass Sie Zeichenfolgen verkettet haben +, um aussagekräftige Sätze zu bilden. Das funktioniert, aber es gibt ein großes Problem, wenn Sie Variablen unterschiedlichen Typs verwenden möchten.

name = "Eric"
age = 14
job = "Comedian"
print("Hello " + name  + "You are " + age + " years old and you are a " + comedian)

TypeError: Kann nur str (nicht "int") mit str verketten

Verwenden Sie einfach die F-Strings von Python 3 . Setzen Sie den Buchstaben 'f' vor"

print(f"Hello {name}, you are {age} years old ")

Reiniger.

Rückgabewert von userinput()

Was Sie gerade tun, ist die Rückgabe eines Tupels von choiceund name. Es ist besser, wenn Sie sie so lassen, wie sie sind, weil Sie später davon abschneiden, nur um sie wieder zu bekommen. Dies bedeutet, dass Sie dies direkt tun

return name, choice

# Calling the function


name, choice = userinput()

Codestruktur

Ein paar Punkte

  • Fragen Sie nicht "Do you want to play again? "in der play_again()Funktion. Der Grund, warum Sie diese Funktion aufgerufen haben, sollte sein, dass der Benutzer erneut spielen möchte. Bewegen Sie dies zu einer playgame()Funktion, die user_input()jedes Mal aufgerufen wird, wenn der Benutzer das Spiel spielen möchte, und brechen Sie die Schleife nur ab, wenn der Benutzer 'n'oder eingibt"no"

  • spaces = spaces + 1 kann vereinfacht werden in spaces += 1

  • Verschieben Sie den Teil, in dem Sie die Anzahl der Zeichen zählen, in eine separate Funktion, die eine Ganzzahl zurückgibt. Ihre play_game()Funktion macht also nichts anderes als das Spiel zu spielen . Wenn Sie die Zeichen brauchen , number_of_char = character_len( name ).

  • Verwenden Sie zur Verdeutlichung die Aufzählung .

Eine verbesserte Version des Codes

from enum import Enum

class PrintChoices(Enum):
    number_of_char = 'c'
    reversed_name = 'r'
    exit_choice = 'e'


def find_num_of_char(name):
    return len(name) - name.count(' ') 

def reverse_name(name):
    return name[::-1]

def user_input():
    name = input("Enter your name: " )
    choice = input("Would you like to (r)everse your name\n or would you like to print the number of (c)haracters or (e)xit?: ")
    return name, choice

def clear_screen():
    print(chr(27) + "[2J")

def play_game():
    while True:
        clear_screen()
        name, choice = user_input()
        if choice == PrintChoices.reversed_name.value:
            print(reverse_name(name))
            input("Press any key to continue...")
        elif choice == PrintChoices.number_of_char.value:
            print(find_num_of_char(name))
            input("Press any key to continue...")
        elif choice == PrintChoices.exit_choice.value:
            break
        else:
            input("Invalid input, Press any key to continue...")



play_game()

Hinweis: Ich habe auch hinzugefügt print(chr(27) + "[2J"), um den Bildschirm zu löschen.

3 AmanDesai Oct 07 2020 at 06:26

Sie können eine bessere Struktur haben. Hier finden Sie eine ausführliche Erklärung. Datenflussfehler, die Sie in der realen Welt nicht machen sollten:

  • Hier machen Ihre Funktionsaufrufe keinen Sinn. Wenn Sie Funktionen definieren und verwenden, definieren Sie sie so, dass sie sich nicht gegenseitig aufrufen, dh es sollte eine Baumstruktur geben. Hauptfunktion steuert alle. (Siehe untenstehenden Code, um einen Einblick zu erhalten.)
  • Ihr Skript kann besser strukturiert sein. Siehe unten Code.

*** PROTIP: Wenn Sie Ihren Code wartbarer machen möchten, teilen Sie ihn in Module auf, fügen Sie alle in verschiedene Dateien ein und importieren Sie sie ***

def take_name_input():
    print('Enter your name:')
    n = input()
    return n

def ask_choice():
   print('Hello, ' + n + ', would you rather (R)everse or (C)ount the letters of your name?')
    a = input()
    return a

def playgame(myname):
    while True:
        choice = ask_choice()
        if choice == 'R':
            print(''.join(reversed(myname)))
        elif choice == 'C':
            for c in list(myname):
                if c == ' ':
                    spaces = spaces + 1
            print('Total # Characters: ' + str(len(myname) - spaces))
        else:
            break

name = take_name_input()
playgame(name)
3 Noname Oct 07 2020 at 06:37

Ich denke, die Struktur ist ziemlich kompliziert, mit Aufrufen von input () und Choosef (), die an mehreren Stellen / Ebenen verteilt sind, daher ist das Programm nicht super lesbar und nicht skalierbar (wenn Sie mehr Benutzereingaben verarbeiten müssten).

Ein besser lesbarer Ansatz wäre eine Hauptschleife wie - im Pseudocode

while True:
  Get user input from 3 choices R / C / E(xit)
  if input = E:
     exit
  else if input = R:
     handle R case
  else 
     handle C case

Auch in Python gibt es eine kürzere Möglichkeit, einen String mit Slicing-Syntax umzukehren: "abc" [:: - 1]

1 Noname Oct 07 2020 at 06:39

Es gibt zwei Bereiche, in denen sich Ihr Code weiter verbessern könnte.

Zuerst können Sie Tools wie flake8 oder pylint ausführen, um Ihren Code auf "Verstöße" gegen PEP8 zu überprüfen. PEP8 ist ein Python-Styleguide, der als De-facto-Style für Python-Code akzeptiert wird. Ich werde mich nicht darauf konzentrieren, da dies meistens ein automatischer Prozess und eine etwas persönliche Entscheidung ist.

Zweitens können Sie Ihren Code in Bezug auf Benennung und Dokumentation verbessern. Dies nennen wir die Lesbarkeit Ihres Codes. Ich habe selbst einen Versuch unternommen und dies ist, was ich (persönlich) als besseren Code empfinde.

Eine Sache, die Sie verbessern können, ist das Entfernen aller Magie aus Ihrem Code. In den beiden folgenden Zeilen legen Sie eine Variable fest uiund übergeben das erste und zweite Element an eine andere Funktion. Wenn ich diese beiden Zeilen sehe, habe ich keine Ahnung, was Sie tun.

ui = userinput()
choosef(ui[0],ui[1])

Dies kann vereinfacht und lesbarer gemacht werden, indem bessere Variablennamen ausgewählt werden und (zumindest in diesem Fall) Tupel entpackt wird:

action, name = get_user_input()
handle_user_action(action, name)

Das obige Beispiel kann auf Ihren gesamten Code angewendet werden. Ich beurteile meinen Code (und den Code, den ich überprüfe) immer mit der Frage: "Wenn ich diesen Codeblock jemandem zeige, ist die Absicht des Codes für die Person, die ihn liest, klar, ohne Kenntnisse des gesamten Programms zu benötigen?"