Python-Collatz-sekvensen
först notera hur du duplicerar beräkningar:
print(num//2)num = num //2
det här kan inte orsaka problem med den här specifika koden, men det är inte en bra praxis. Du gör dubbelt så mycket arbete som du behöver, vilket kan orsaka prestandaproblem när du börjar skriva mer komplicerad kod. Gör beräkningen en gång och spara resultatet. I det här fallet är allt du behöver göra att vända dessa rader och använda num
:
num = num // 2print(num)
se också till att du har rätt avstånd runt operatörer och vara konsekvent.
dina if
och elif
fall är exklusiva för varandra, och din else
ska aldrig hända. Om det första villkoret är sant, måste andra vara falska och vice versa. Det finns inget behov av den andra kontrollen. När du har skrivit om ser du att utskrift i alla fall inte är nödvändigt. Du kan bara skriva ut efter:
while num > 1: if num % 2 == 0: num = num // 2 else: num = 3 * num + 1 print(num)
eftersom du bara återställer num
ett av två alternativ baserat på ett villkor, kan ett villkorligt uttryck också användas här rent:
while num > 1: num = (num // 2) if num % 2 == 0 else (3 * num + 1) print(num)
hängslen är inte nödvändiga, men jag tror att de är användbara här på grund av antalet involverade operatörer.
att skriva ut siffrorna är inte idealiskt här. I de flesta kod måste du kunna använda de data som du producerar. Om du ville analysera den producerade sekvensen, skulle du behöva göra något avlyssna stdout, vilket är dyrt och alltför komplicerat. Gör det till en funktion som ackumuleras och returnerar en lista. I följande exempel lade jag också till några typtips för att göra det tydligare vad typen av data är:
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, ett mycket renare tillvägagångssätt är att göra det till en generator som ger siffrorna:
# 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 finns några anmärkningsvärda saker om getNum
:
Python använder “snake_case”, inte”camelCase”.
din användning av global num
här är onödigt och förvirrande. Precis som tidigare, uttryckligen return
Alla data som funktionen producerar:
def get_num() -> int: raw_num = input("> ") try: return int(raw_num) except ValueError: print('Please enter a number') return get_num()
observera hur istället för att omfördela en global num
, returnerar vi bara numret. Jag delade också ut saker lite och använde några mer lämpliga namn. Konceptuellt skulle jag säga att num = input("> ")
är fel. Vid den tidpunkt som körs innehåller num
inte ett tal (det innehåller en sträng).
Detta är inte en bra användning av rekursion. Det kommer sannolikt inte att orsaka några problem, men om din användare är riktigt dum och går in i fel data ~1000 gånger kommer ditt program att krascha. Använd bara en slinga:
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, var försiktig med rekursion i fall där du inte har några garantier för hur många gånger funktionen kommer att återkomma.
jag skulle också förmodligen namnge detta något närmare ask_for_num
. “get” gör det inte mycket tydligt om var uppgifterna kommer ifrån.
taget helt och hållet kommer du att sluta 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 användas som:
num = ask_for_num()for n in collatz_gen(num): print(n)