Juego de consola de Python simple con flujo de código ineficiente -- python camp codereview Relacionados El problema

Simple Python Console Game With Inefficient Code Flow


13
vote

problema

Español

Hice un programa simple como ejercicio para mejorar mi flujo de código en Python, lo que hace lo siguiente:

  1. le pide al usuario que ingrese su nombre
  2. los presenta con una opción para imprimir su nombre a la inversa, o imprimir el número de caracteres
  3. Después de imprimir la salida, se le pregunta al usuario si quiere "volver a jugar". Si no, sale

¿He hecho algo especialmente tonto? ¿Alguna fruta baja colgante? ¿Mejor práctica que desconoce?

  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])   
Original en ingles

I made a simple program as an exercise in improving my code flow in Python, which does the following:

  1. asks user to input their name
  2. presents them with a choice to either print their name in reverse, or print the number of characters
  3. after the output is printed, the user is asked if they want to "play again". if not, exits

Have I done anything especially goofy? Any low hanging fruit? Best practice I'm unaware of?

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]) 
  
       
       

Lista de respuestas

31
 
vote
vote
La mejor respuesta
 

Trate de olvidar todo lo que conoce sobre el código, y asuma que no es el autor. Imagínese para ser una tercera persona que lee el código, no sabe nada al respecto y simplemente leerlo por primera vez.

  obj.__proto__ = ... statement2  

BURNHIGHT, obj.__proto__ = ... statement33 debe tomar algunas entradas y colocarla en obj.__proto__ = ... statement4 . Tiene sentido, pero ¿qué es obj.__proto__ = ... statement5 ?.

Convención de nombramiento

Use significativo nombres para funciones y variables. tomar este ejemplo

  obj.__proto__ = ... statement6  

¿Qué es obj.__proto__ = ... statement7 y obj.__proto__ = ... statement88 al lector? ¿Es ese el precio de algo?

  obj.__proto__ = ... statement9  

ahhh, ahora, ahora sé exactamente qué significa [[Prototype]]0 . Entonces, si lo uso en algún lugar, el lector también sabrá lo que quiero decir exactamente. Esta es una parte importante de escribir código limpio.

Otro aspecto es el estilo. Hay algunas maneras en que puedo escribir Entrada de usuario *

  [[Prototype]]1  

¿Cuál debería seguir?

Tener una convención de nomenclatura consistente, el código Python sigue al pep- 8 Convención de nombramiento. Cuando digo sigue, quiero decir que se recomienda que también lo sigas, ya que otras bibliotecas de Python también usan esto. Hace que el código se vea más limpio.

Cosas como las funciones siguientes: [[Prototype]]2

Siga las clases: [[Prototype]]3

Puede leer el enlace para obtener más información.

Tomando la entrada en Python

  [[Prototype]]4  

Claramente, desea mostrar un mensaje al usuario antes de que ingrese algo. Esta es la razón por la cual el 99887766555443345 tiene algo llamado PROMPT .

[[Prototype]]6

Puede mostrar el mensaje entre el [[Prototype]]7 . Esto elimina la línea adicional. También tenga en cuenta que cambié [[Prototype]]8 a [[Prototype]]9 Por las razones por las que mencioné anteriormente.

Formato de cadenas

De su código, puedo ver que usted concatenó cadenas con [[Prototype]]0 para formar oraciones significativas. Eso funciona, pero hay un gran problema cuando quiere usar variables de diferentes tipos.

  [[Prototype]]1  

TypeError: solo puede concatenar STR (no "INT") a STR

Simplemente use Python 3's f-strings . Coloque la letra 'f' antes [[Prototype]]2

  [[Prototype]]3  

limpiador.

Valor de retorno de [[Prototype]]4

Lo que está haciendo actualmente está devolviendo una tupla de [[Prototype]]5 y [[Prototype]]6 . Es mejor que los mantengas, ya que son porque más tarde, lo rebanando solo para volver a conseguirlos. Esto significa que usted hace directamente

  [[Prototype]]7  

Estructura de código

Pareja de puntos

  • NO PREGUNTE [[Prototype]]8 En la función [[Prototype]]9 . La razón por la que usted llamó esa función debe ser porque el usuario quiere volver a jugar. Mueve eso a una función [[Prototype]]0655443360 que llamará [[Prototype]]1 Cada vez que el usuario quiera reproducir el juego, y romper el bucle solo si el usuario entra [[Prototype]]2 O [[Prototype]]3

  • [[Prototype]]4 se puede simplificar en [[Prototype]]5

  • Mueva la parte donde cuente la cantidad de caracteres en una función separada que devolverá un entero. Entonces, la función [[Prototype]]6655443366 no hace nada que no sea toque el juego . Cuando necesita los caracteres, [[Prototype]]7 .

  • Use enum para clari y.

una versión mejorada del código

  [[Prototype]]8  

Nota: También he agregado [[Prototype]]9 para borrar la pantalla.

 

Try to forget everything that you know about the code, and assume that you aren't the author. Imagine yourself to be a third person reading the code, he/she knows nothing about it and just reading it for the first time.

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

Alright, userinput() must take some input and put it into ui. Makes sense, but what is choosef()?.

Naming convention

Use meaningful names for functions and variables. take this example

x = 3.14 y = 24 

what is x and y to the reader? Is that the price of something?

pi_value = 3.14 number_of_hours = 24 

Ahhh okay, now I know exactly what 3.14 means. So If I use it somewhere the reader will also know what I exactly mean. This is an important part of writing clean code.

Another aspect is the style. There are a few ways I can write user input*

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

Which one should I follow?

To have a consistent naming convention, python code follows the PEP-8 naming convention. When I say follows, I mean that it is recommended that you should follow it too as other python libraries also use this. It makes the code look cleaner.

Things like functions follow : lower_snake_case

Classes follow: CamelCase

You can read the link for more information.

Taking input in Python

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

Clearly, you want to display a message to the user before he enters something. This is why the input() function has something called input prompt.

name = input("Enter your name: ")

You can display the message between the (). This removes the additional line. Also note that I changed n to name for the reasons I mentioned above.

Formatting strings

From your code, I can see that you concatenated strings with + to form meaningful sentences. That works but there is a huge problem when you want to use variables of different types.

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

TypeError: can only concatenate str (not "int") to str

Simply use Python 3's f-strings. Place the letter 'f' before "

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

Cleaner.

return value from userinput()

What you are currently doing is returning a tuple of choice and name. It's better that you keep them as they are because later on, you slice from it just to get them again. This means you directly do

return name, choice  # Calling the function   name, choice = userinput() 

Code structure

Couple of points

  • Do not ask "Do you want to play again? " in the play_again() function. The reason you called that function should be because the user wants to play again. Move that to a playgame() function which will call user_input() every time the user wants to play the game, and break from the loop only if the user enters 'n' or "no"

  • spaces = spaces + 1 can be simplified into spaces += 1

  • Move the part where you count the number of characters into a separate function which will return an integer. So your play_game() function doesn't do anything other than play the game. When you need the characters , number_of_char = character_len( name ).

  • Use enum for clarity.

An improved version of the code

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() 

Note: I have also added print(chr(27) + "[2J") to clear the screen.

 
 
         
         
3
 
vote

Puedes tener una mejor estructura. Aquí está la explicación detallada. Errores de flujo de datos que no debe hacer en el mundo real:

  • Aquí, las llamadas de su función no tienen sentido. Cada vez que se definen y usas funciones, definen de tal manera que no se llamen entre sí. mi. Debe haber estructura de árboles. La función principal controlará a todos. (Vea por debajo del código para vislumbrar.)
  • Tu script puede tener una mejor estructura. Ver por debajo del código.

*** Protip: Si desea que su código sea más mantenido, divídalo en módulos y colóquelos en diferentes archivos e importe ellos ***

  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)   
 

You can have a better structure. Here is detailed explanation. Data Flow Errors which you should not do in real world:

  • Here, your function calls don't make sense. Whenever you define and use functions, define them in such a way that they don't call each other i. e. there should be tree structure. Main function will control all. (See Below Code to get glimpse.)
  • Your script can have better structure. See Below Code.

*** PROTIP: If you want to make your code more maintainable, break it into modules and put all of them in different files and import them ***

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
 
vote

Creo que la estructura está bastante complicada, con las llamadas a la entrada () y elección () dispersos en múltiples lugares / niveles, por lo que el programa no es súper legible y no escalable (si tuvo que manejar más entradas de usuario). < / p>

Un enfoque más legible sería un bucle principal como - en el código pseudo

  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   

También en Python Hay una forma más corta de revertir una cadena con sintaxis de rebanar: "ABC" [:: - 1]

 

I think the structure is quite convoluted, with calls to input() and choosef() scattered in multiple places/levels, thus the program is not super readable and not scalable (if you had to handle more user inputs).

A more readable approach would be a main loop like - in pseudo code

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 

Also in python there is a shorter way to reverse a string with slicing syntax: "abc"[::-1]

 
 
     
     
1
 
vote

Hay dos áreas donde su código podría mejorar aún más.

Primero, puede ejecutar herramientas como Flake8 o Pylint para verificar su código para "violaciones" de PEP8. PEP8 es una guía de estilo Python que se acepta como el estilo de facto para el código de Python. No me enfocaré en esto, ya que en su mayoría un proceso automático y una elección algo personal.

En segundo lugar, puede realizar algunas mejoras en su código con respecto a la nombramiento y la documentación. Esto es lo que llamamos la legibilidad de su código. Me he disparado a esto mismo y esto es lo que yo (personalmente) encuentro un código mejor.

Una cosa que puede mejorar es eliminar todas las MAGIC de su código. En las dos líneas a continuación, configura una variable ui y luego pase el primer y segundo elemento a otra función. Si veo estas dos líneas, no tengo idea de lo que estás haciendo.

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

Esto se puede simplificar y hacer más legible seleccionando mejores nombres de variables y (en este caso, al menos) usando Tuple Desembalaje:

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

El ejemplo anterior se puede aplicar a lo largo de su código. Siempre juzgo mi código (y el código que reviso) con la pregunta: "Si muestro este bloque de código a alguien, es la intención del código claro a la persona que la lee, sin requerir conocimiento de todo el programa ? "

 

There are two area's where your code could improve further.

First you can run tools like flake8 or pylint to check your code for 'violations' of PEP8. PEP8 is a Python style guide that is accepted as the de facto style for Python code. I won't focus on this since this mostly an automatic process and a somewhat personal choice.

Secondly you can make some improvements to your code with regards to naming and documentation. This is what we call the readability of your code. I've taken a shot at this myself and this is what I (personally) find to be better code.

One thing you can improve is removing all magic from your code. In the two lines below you set a variable ui and then pass the first and second element to another function. If I see these two lines, I have no idea what you're doing.

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

This can be simplified and made more readable by selecting better variable names and (in this case at least) using tuple unpacking:

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

The example above can be applied throughout your code. I always judge my code (and the code I review) with the question: "If I show this block of code to someone, is the intention of the code clear to the person reading it, without requiring knowledge of the entire program?"

 
 
 
 

Relacionados problema

6  Unión profunda / recursiva, todos, cualquiera, suma, len  ( Deep recursive join all any sum len ) 
Sigo olvidando que el estándar join() solo puede tomar una sola itinerable, así que hice algunas funciones que actúen recursivamente en cualquier argumento ...

56  Proyecto Euler Problema 1 en Python - Múltiples de 3 y 5  ( Project euler problem 1 in python multiples of 3 and 5 ) 
Me gustaría sugerencias para optimizar esta solución de fuerza bruta a problema 1 . El algoritmo actualmente comprueba cada entero entre 3 y 1000. Me gustarí...

2  Dos formas de aleatorias aleatoriamente las tarjetas  ( Two ways to randomly shuffle cards ) 
Aquí hay dos implementaciones que escribí para aleatorizar las tarjetas. El primer método ( dt5 ) Selecciona una tarjeta aleatoria, luego lo quita al frent...

2  Análisis de XML con doble etiquetas anidadas usando MINDOM  ( Parsing xml with double nested tags using mindom ) 
Quiero recuperar la identificación y el nombre por habilidad. Funciona pero esta bien hecho? Me gustaría quedarme con minidom, pero todos los consejos serán a...

4  Atomas Clone en Python  ( Atomas clone in python ) 
Aquí está mi clon de mierda de atomas , un juego de rompecabezas donde combina pequeños átomos en otros más valiosos. 9988776655544337 ¿Hay algún códig...

6  Compara el último tiempo de modificación con tiempo especificado  ( Compare last modification time with specfied time ) 
Estoy escribiendo una función en Python que compara el tiempo de modificación de un archivo en Linux (usando OS.STAT) con un tiempo específico y compare las f...

61  Uso de funciones separadas para Project Euler 1  ( Using separate functions for project euler 1 ) 
Comencé a programar con Java y C ++, así que estoy acostumbrado a tener una función "principal" que llama a otras funciones que realizan el trabajo real. En l...

6  Comprobando una cuadrícula de palabras  ( Checking a word grid ) 
Escribí este programa donde puede ingresar x cantidad de palabras que de longitud x que comprueba si la cuadrícula se formó son las mismas palabras vertic...

6  Diseño de un juego de acorazado simple en Python  ( Designing a simple battleship game in python ) 
Estoy tratando de codificar acorazado . Debe ser un juego de texto de un jugador contra la computadora donde el jugador de computadora y el jugador humano se...

3  Usuario rápido para algunos números, luego imprime el máximo y min  ( Prompt user for some numbers then print the max and min ) 
La función de este programa está solicitando repetidamente a un usuario para números enteros hasta que el usuario ingrese en 'done' . Una vez que se ingresa ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos