Python-Collatz Sequence
legg først merke til hvordan du dupliserer beregninger:
print(num//2)num = num //2
Dette kan ikke forårsake problemer med denne spesifikke koden, men det er ikke en god praksis. Du gjør dobbelt så mye arbeid som du trenger, noe som kan føre til ytelsesproblemer når du begynner å skrive mer komplisert kode. Gjør beregningen en gang, og lagre resultatet. I dette tilfellet er alt du trenger å gjøre, reversere disse linjene og bruk num
:
num = num // 2print(num)
sørg også for at du har riktig avstand rundt operatører, og vær konsekvent.
dine if
og elif
saker er eksklusive for hverandre, og din else
skal aldri skje. Hvis den første betingelsen er sant, må andre være falske og omvendt. Det er ikke behov for den andre sjekken. Når omskrevet, vil du se at utskrift i alle tilfeller er ikke nødvendig. Du kan bare skrive ut etter:
while num > 1: if num % 2 == 0: num = num // 2 else: num = 3 * num + 1 print(num)
Siden du bare reassinging num
en av to alternativer basert på en tilstand, kan et betinget uttrykk også brukes her rent:
while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) print(num)
bøylene er ikke nødvendige, men jeg tror de er nyttige her på grunn av antall involverte operatører.
Utskrift av tallene er ikke ideelt her. I de fleste kode må du kunne bruke dataene du produserer. Hvis du ønsket å analysere den produserte sekvensen, må du gjøre noe fange stdout, som er dyrt og altfor komplisert. Gjør det til en funksjon som akkumulerer og returnerer en liste. I de følgende eksemplene har jeg også lagt til noen typehint for å gjøre det tydeligere hva typen av dataene er:
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
Eller en mye renere tilnærming er å gjøre det til en generator som gir tallene:
# 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))
Det er noen bemerkelsesverdige ting om getNum
:
Python bruker “snake_case”, ikke”camelCase”.
din bruk av global num
her er unødvendig og forvirrende. Akkurat som før, eksplisitt return
alle data som funksjonen produserer:
def get_num() -> int: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number') return get_num()
Legg merke til hvordan i stedet for å tilordne en global num
, returnerer vi bare nummeret. Jeg spredte også ting litt, og brukte noen mer passende navn. Konseptuelt vil jeg si at num = input("> ")
er feil. Når det kjører, inneholder num
ikke et tall(det inneholder en streng).
Dette er ikke en god bruk av rekursjon. Det vil sannsynligvis ikke gi deg noen problemer, men hvis brukeren din er veldig dum og går inn i feil data ~1000 ganger, vil programmet krasje. Bare bruk en løkke:
def get_num() -> int: while True: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number')
på Språk som Python, vær forsiktig med rekursjon i tilfeller der du ikke har noen garantier for hvor mange ganger funksjonen vil rekursere.
jeg vil også trolig nevne dette noe nærmere ask_for_num
. “get” gjør det ikke veldig klart om hvor dataene kommer fra.
Tatt helt, vil du ende opp med:
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')
Som kan brukes som:
num = ask_for_num()for n in collatz_gen(num): print(n)