Python-The Collatz Sequence
merk eerst op hoe je berekeningen dupliceert:
print(num//2)num = num //2
dit mag geen problemen veroorzaken met deze specifieke code, maar het is geen goede praktijk. Je doet twee keer zoveel werk als je nodig hebt, wat problemen met de prestaties kan veroorzaken als je begint met het schrijven van meer ingewikkelde code. Doe de berekening één keer en sla het resultaat op. In dit geval hoeft u alleen deze regels om te keren en num
te gebruiken:
num = num // 2print(num)
zorg er ook voor dat u de juiste spatiëring rond operators hebt en wees consistent.
uw if
en elif
gevallen zijn exclusief van elkaar, en uw else
mag nooit gebeuren. Als de eerste voorwaarde Waar is, dan moet andere onwaar zijn en vice versa. De tweede cheque is niet nodig. Eenmaal herschreven, zult u zien dat afdrukken in elk geval niet nodig is. U kunt gewoon afdrukken na:
while num > 1: if num % 2 == 0: num = num // 2 else: num = 3 * num + 1 print(num)
omdat u net num
een van de twee opties opnieuw maakt op basis van een voorwaarde, kan hier ook een voorwaardelijke expressie netjes worden gebruikt:
while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) print(num)
de accolades zijn niet nodig, maar ik denk dat ze hier nuttig zijn vanwege het aantal betrokken operators.
het afdrukken van de nummers is hier niet ideaal. In de meeste code moet je de gegevens kunnen gebruiken die je produceert. Als je de geproduceerde sequentie wilt analyseren, moet je iets doen om de stdout te onderscheppen, wat duur en overdreven ingewikkeld is. Maak er een functie van die een lijst verzamelt en retourneert. In de volgende voorbeelden heb ik ook een aantal type hints toegevoegd om het duidelijker te maken wat het type van de gegevens is:
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
of, een veel schonere aanpak is om het een generator te maken die de getallen oplevert:
# 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))
er zijn een paar opmerkelijke dingen over getNum
:
Python gebruikt “snake_case”, niet”camelCase”.
uw gebruik van global num
hier is onnodig en verwarrend. Net als voorheen, expliciet return
alle gegevens die de functie produceert:
def get_num() -> int: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number') return get_num()
merk op hoe we in plaats van een globale num
opnieuw toe te wijzen, het nummer retourneren. Ik heb ook de dingen een beetje uit elkaar gehaald, en een aantal meer toepasselijke namen gebruikt. Conceptueel zou ik zeggen dat num = input("> ")
verkeerd is. Op het moment dat dat wordt uitgevoerd, bevat num
geen getal (het bevat een tekenreeks).
dit is geen goed gebruik van recursie. Het zal u waarschijnlijk geen problemen veroorzaken, maar als uw gebruiker echt dom is en verkeerde gegevens ~1000 keer invoert, zal uw programma crashen. Gebruik gewoon een lus:
def get_num() -> int: while True: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number')
in talen zoals Python, wees voorzichtig met recursie in gevallen waar je geen garanties over hoe vaak de functie zal recursen.
ik zou dit waarschijnlijk ook iets dichter bij ask_for_num
noemen. “get” maakt het niet erg duidelijk over waar de gegevens vandaan komen.
in totaal eindig je met:
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')
die kan worden gebruikt als:
num = ask_for_num()for n in collatz_gen(num): print(n)