Python-The Collatz Sequence
First, note how you’re duplicating calculations:
print(num//2)num = num //2
isto pode não causar problemas com este código específico, mas não é uma boa prática. Estás a fazer o dobro do trabalho que precisas, o que pode causar problemas de desempenho quando começas a escrever código mais complicado. Faça o cálculo uma vez, e salve o resultado. Neste caso, porém, tudo o que você precisa fazer é inverter essas linhas e usar num
:
num = num // 2print(num)
também, certifique-se de que tem espaçamento adequado em torno dos operadores, e seja consistente.Os seus casos são exclusivos uns dos outros, e os seus casos nunca devem acontecer. Se a primeira condição é verdadeira, então a outra deve ser falsa e vice-versa. Não há necessidade do segundo cheque. Uma vez reescrito, verá que imprimir em todos os casos não é necessário. Você pode imprimir depois:
while num > 1: if num % 2 == 0: num = num // 2 else: num = 3 * num + 1 print(num)
uma vez que você está apenas reassumindo num
uma de duas opções com base em uma condição, uma expressão condicional pode ser usada aqui limpo também:Os suspensórios não são necessários, mas acho que são úteis aqui devido ao número de operadores envolvidos.Imprimir os números não é ideal aqui. Na maioria dos códigos, você precisa ser capaz de usar os dados que você produz. Se você quisesse analisar a sequência produzida, você teria que fazer algo interceptar o stdout, que é caro e excessivamente complicado. Faça dela uma função que acumula e retorna uma lista. Nos seguintes exemplos, eu também adicionei algumas dicas de tipo para torná-lo mais claro qual o tipo de dados é:
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
Ou, muito mais claro abordagem é a de fazer um gerador que produz os 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))
Há algumas coisas notáveis sobre getNum
:
Python usa “snake_case”, não “camelCase”.O seu uso de global num
aqui é desnecessário e confuso. Tal como antes, explicitamente return
quaisquer dados que a função produza:
def get_num() -> int: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number') return get_num()
Note como em vez de reassignar um global num
, estamos apenas retornando o número. Eu também espaçei um pouco as coisas, e usei alguns nomes mais apropriados. Conceitualmente, eu diria que num = input("> ")
está errado. No momento em que corre, num
não contém um número (Ele contém uma cadeia).
este não é um bom uso da recursão. É provável que não lhe cause quaisquer problemas, mas se o seu utilizador for realmente burro e introduzir dados errados ~1000 vezes, o seu programa irá estoirar. Basta usar um loop:
def get_num() -> int: while True: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number')
em linguagens como Python, tenha cuidado ao usar a recursão nos casos em que você não tem nenhuma garantia sobre quantas vezes a função irá recursar.
eu também provavelmente nomearia isto algo mais próximo de ask_for_num
. “get” não deixa muito claro de onde os dados estão vindo.Tomado ao todo, você vai acabar com:
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 pode ser utilizado como:
num = ask_for_num()for n in collatz_gen(num): print(n)