Python-La Secuencia de Collatz
En primer lugar, observe cómo está duplicando cálculos:
print(num//2)num = num //2
Esto puede no causar problemas con este código específico, pero no es una buena práctica. Estás haciendo el doble de trabajo que necesitas, lo que puede causar problemas de rendimiento una vez que empiezas a escribir código más complicado. Haga el cálculo una vez y guarde el resultado. En este caso, sin embargo, todo lo que necesita hacer es invertir esas líneas y usar num
:
num = num // 2print(num)
Además, asegúrese de tener el espaciado adecuado alrededor de los operadores y sea consistente.
Sus casos if
y elif
son exclusivos el uno del otro, y su else
nunca debería suceder. Si la primera condición es verdadera, entonces la otra debe ser falsa y viceversa. No hay necesidad de la segunda comprobación. Una vez reescrita, verá que la impresión en todos los casos no es necesaria. Puede imprimir después de:
while num > 1: if num % 2 == 0: num = num // 2 else: num = 3 * num + 1 print(num)
Dado que solo está reevaluando num
una de las dos opciones basadas en una condición, también se puede usar una expresión condicional aquí de forma limpia:
while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) print(num)
Los frenos no son necesarios, pero creo que son útiles aquí debido al número de operadores involucrados.
Imprimir los números no es ideal aquí. En la mayoría de los códigos, necesita poder usar los datos que produce. Si desea analizar la secuencia producida, tendría que hacer algo para interceptar la salida estándar, que es costosa y excesivamente complicada. Conviértala en una función que acumule y devuelva una lista. En los siguientes ejemplos, también agregué algunas sugerencias de tipo para aclarar cuál es el tipo de datos:
from typing import Listdef collatz(starting_num: int) -> List: nums = num = starting_num while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) nums.append(num) return nums
O, un enfoque mucho más limpio es convertirlo en un generador que produzca los números:
# Calling this function returns a generator that produces ints# Ignore the two Nones, as they aren't needed for this kind of generatordef collatz_gen(starting_num: int) -> Generator: yield starting_num num = starting_num while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) yield num>>> list(collatz_gen(5))
Hay algunas cosas notables sobre getNum
:
Python usa “snake_case”, no”camelCase”.
Su uso de global num
aquí es innecesario y confuso. Al igual que antes, explícitamente return
cualquier dato que produzca la función:
def get_num() -> int: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number') return get_num()
Ten en cuenta que, en lugar de reasignar un num
global, solo devolvemos el número. También espacié un poco las cosas, y usé algunos nombres más apropiados. Conceptualmente, diría que num = input("> ")
está mal. En el momento en que se ejecuta, num
no contiene un número (contiene una cadena).
Este no es un buen uso de la recursividad. Es probable que no le cause ningún problema, pero si su usuario es realmente tonto y ingresa datos incorrectos ~1000 veces, su programa se bloqueará. Solo usa un bucle:
def get_num() -> int: while True: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number')
En lenguajes como Python, tenga cuidado con el uso de recursividad en casos en los que no tenga garantías sobre cuántas veces se repetirá la función.
Probablemente también lo llamaría algo más cercano a ask_for_num
. “obtener” no deja muy claro de dónde vienen los datos.
Tomados en conjunto, terminarás con:
from typing import Generatordef collatz_gen(starting_num: int) -> Generator: yield starting_num num = starting_num while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) yield numdef ask_for_num() -> int: while True: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number')
Que se puede utilizar como:
num = ask_for_num()for n in collatz_gen(num): print(n)