Python-The Collatz Sequence
először is, vegye figyelembe, hogyan duplikálja a számításokat:
print(num//2)num = num //2
lehet, hogy ez nem okoz problémát ezzel a konkrét kóddal, de ez nem jó gyakorlat. Kétszer annyi munkát végez, mint amennyire szüksége van, ami teljesítményproblémákat okozhat, ha bonyolultabb kódot ír. Végezze el a számítást egyszer, és mentse el az eredményt. Ebben az esetben azonban csak annyit kell tennie, hogy megfordítja ezeket a sorokat, és num
:
num = num // 2print(num)
ezenkívül győződjön meg arról, hogy megfelelő a térköz az operátorok körül, és legyen következetes.
a if
és elif
esetek kizárják egymást, és a else
soha nem történhet meg. Ha az első feltétel igaz, akkor a másiknak hamisnak kell lennie, és fordítva. Nincs szükség a második ellenőrzésre. Miután átírta, látni fogja, hogy a nyomtatás minden esetben nem szükséges. Akkor csak nyomtatni után:
while num > 1: if num % 2 == 0: num = num // 2 else: num = 3 * num + 1 print(num)
mivel csak egy feltételen alapuló két lehetőség egyikét újragondolja num
, a feltételes kifejezés itt is tisztán használható:
while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) print(num)
a zárójelek nem szükségesek, de azt hiszem, itt hasznosak az érintett operátorok száma miatt.
a számok nyomtatása itt nem ideális. A legtöbb kódban képesnek kell lennie az előállított adatok felhasználására. Ha az előállított szekvenciát szeretné elemezni, akkor valamit meg kell tennie az stdout elfogásához, ami drága és túl bonyolult. Legyen ez egy függvény, amely felhalmozódik és visszaad egy listát. A következő példákban, hozzáadtam néhány típusú tippet is, hogy világosabbá tegyem az adatok típusát:
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
vagy sokkal tisztább megközelítés az, ha generátort készítünk, amely megadja a számokat:
# 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))
van néhány figyelemre méltó dolog getNum
:
a Python a “snake_case” – t használja, nem a “camelCase” – t.
a global num
használata itt szükségtelen és zavaró. Csakúgy, mint korábban, explicit return
minden olyan adat, amelyet a függvény állít elő:
def get_num() -> int: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number') return get_num()
vegye figyelembe, hogy a globális num
hozzárendelése helyett csak a számot adjuk vissza. Én is egy kicsit szétosztottam a dolgokat, és néhány megfelelő nevet használtam. Fogalmilag azt mondanám, hogy a num = input("> ")
helytelen. Abban az időben, hogy fut, num
nem tartalmaz számot (tartalmaz egy karakterláncot).
ez nem jó haszna a rekurziónak. Valószínűleg nem okoz problémát, de ha a felhasználó valóban hülye, és hibás adatokat ad meg ~1000-szer, a program összeomlik. Csak használjon hurkot:
def get_num() -> int: while True: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number')
az olyan nyelveken, mint a Python, legyen óvatos a rekurzió használatával azokban az esetekben, amikor nincs garancia arra, hogy a függvény hányszor ismétlődik.
valószínűleg ezt is megnevezném valami közelebb a ask_for_num
– hez. a ” get ” nem teszi egyértelművé, hogy honnan származnak az adatok.
összességében, akkor a végén:
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')
amely használható, mint:
num = ask_for_num()for n in collatz_gen(num): print(n)