Python-The Collatz Sequence
Innanzitutto, nota come stai duplicando i calcoli:
print(num//2)num = num //2
Ciò potrebbe non causare problemi con questo codice specifico, ma non è una buona pratica. Stai facendo il doppio del lavoro necessario, il che può causare problemi di prestazioni una volta iniziato a scrivere codice più complicato. Esegui il calcolo una volta e salva il risultato. In questo caso, però, tutto ciò che devi fare è invertire quelle linee e usare num
:
num = num // 2print(num)
Inoltre, assicurati di avere una spaziatura adeguata attorno agli operatori ed essere coerente.
I tuoi casi if
e elif
sono esclusivi l’uno dell’altro e il tuo else
non dovrebbe mai accadere. Se la prima condizione è vera, allora l’altra deve essere falsa e viceversa. Non c’è bisogno del secondo controllo. Una volta riscritto, vedrai che la stampa in ogni caso non è necessaria. Si può solo stampare dopo:
while num > 1: if num % 2 == 0: num = num // 2 else: num = 3 * num + 1 print(num)
Dal momento che stai solo riassegnando num
una delle due opzioni basate su una condizione, un’espressione condizionale può essere utilizzata anche qui in modo pulito:
while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) print(num)
Le parentesi graffe non sono necessarie, ma penso che siano utili qui a causa del numero di operatori coinvolti.
Stampare i numeri non è l’ideale qui. Nella maggior parte del codice, è necessario essere in grado di utilizzare i dati che si producono. Se volessi analizzare la sequenza prodotta, dovresti fare qualcosa per intercettare lo stdout, che è costoso ed eccessivamente complicato. Rendilo una funzione che accumula e restituisce un elenco. Negli esempi seguenti, ho anche aggiunto alcuni suggerimenti di tipo per rendere più chiaro quale sia il tipo di dati:
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
Oppure, un approccio molto più pulito è quello di renderlo un generatore che produce i numeri:
# 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))
Ci sono alcune cose notevoli su getNum
:
Python usa “snake_case”, non”camelCase”.
L’uso di global num
qui non è necessario e confuso. Proprio come prima, esplicitamente return
tutti i dati che la funzione produce:
def get_num() -> int: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number') return get_num()
Nota come invece di riassegnare un num
globale, stiamo solo restituendo il numero. Ho anche distanziato un po ‘ le cose e ho usato alcuni nomi più appropriati. Concettualmente, direi che num = input("> ")
è sbagliato. Nel momento in cui viene eseguito, num
non contiene un numero (contiene una stringa).
Questo non è un buon uso della ricorsione. Probabilmente non ti causerà alcun problema, ma se il tuo utente è davvero stupido e inserisce dati errati ~1000 volte, il tuo programma si bloccherà. Basta usare un ciclo:
def get_num() -> int: while True: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number')
In linguaggi come Python, fai attenzione a usare la ricorsione nei casi in cui non hai garanzie su quante volte la funzione si ripresenterà.
Probabilmente chiamerei anche questo qualcosa di più vicino a ask_for_num
. “get” non rende molto chiaro da dove provengono i dati.
Preso del tutto, finirai 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')
Che può essere utilizzato come:
num = ask_for_num()for n in collatz_gen(num): print(n)