Python – Collatz Sekvence
za Prvé, všimněte si, jak jste duplikování výpočty:
print(num//2)num = num //2
To může způsobit problémy s touto konkrétní kód, ale to není dobré praxe. Děláte dvakrát tolik práce, než potřebujete, což může způsobit problémy s výkonem, jakmile začnete psát složitější kód. Proveďte výpočet jednou a výsledek uložte. V tomto případě však vše, co musíte udělat, je obrátit tyto řádky a použít num
:
num = num // 2print(num)
také se ujistěte, že máte správné mezery kolem operátorů a buďte konzistentní.
vaše případy if
a elif
se navzájem vylučují a vaše else
by se nikdy nemělo stát. Pokud je první podmínka pravdivá, pak ostatní musí být nepravdivé a naopak. Není potřeba druhá kontrola. Po přepsání uvidíte, že tisk v každém případě není nutný. Stačí vytisknout po:
while num > 1: if num % 2 == 0: num = num // 2 else: num = 3 * num + 1 print(num)
protože právě přehodnocujete num
jednu ze dvou možností založených na podmínce, lze zde použít i podmíněný výraz:
while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) print(num)
závorky nejsou nutné, ale myslím, že jsou zde užitečné vzhledem k počtu zapojených operátorů.
tisk čísel zde není ideální. Ve většině kódu musíte být schopni používat data, která vytvoříte. Pokud byste chtěli analyzovat vyrobenou sekvenci, museli byste udělat něco zachytit stdout, což je drahé a příliš komplikované. Ať je to funkce, která se hromadí a vrátí seznam. V následujících příkladech jsem také přidal několik typových rad, aby bylo jasnější, jaký je typ dat:
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
Nebo, mnohem čistší přístup je, aby se to generátor, který dává čísla:
# 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))
Tam je několik pozoruhodných věcí, o getNum
:
Python používá “snake_case”, ne “camelCase”.
vaše použití global num
zde je zbytečné a matoucí. Stejně jako předtím, výslovně return
všechna data, která funkce produkuje:
def get_num() -> int: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number') return get_num()
Všimněte si, jak namísto přiřazení globální num
, my jsme jen vrací číslo. Také jsem trochu rozložil věci, a použil některá vhodnější jména. Koncepčně bych řekl, že num = input("> ")
je špatně. V době spuštění num
neobsahuje číslo (obsahuje řetězec).
Toto není dobré využití rekurze. Pravděpodobně vám nezpůsobí žádné problémy, ale pokud je váš uživatel opravdu hloupý a zadá nesprávná data ~1000krát, váš program se zhroutí. Stačí použít smyčku:
def get_num() -> int: while True: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number')
V jazycích, jako je Python, buďte opatrní, pomocí rekurze v případech, kdy nemáte žádné záruky o tom, kolikrát funkce bude recurse.
také bych pravděpodobně pojmenoval toto něco blíže ask_for_num
. “get” nedává jasně najevo, odkud data pocházejí.
přijato celkem, skončíte s:
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')
které lze použít jako:
num = ask_for_num()for n in collatz_gen(num): print(n)