You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

Dette kode-eksemplet implementerer en enkel kalkulator og illustrerer ulike aspekter ved (kjøring av) Python-programmer.

RPN-kalkulatorer (RPN står for Reverse Polish Notation, se http://en.wikipedia.org/wiki/Reverse_Polish_notation) er kalkulatorer der operander (verdier) angis først og så operatorene (operasjoner), istedenfor den vanlige infix-notasjonen. For å regne ut 1 + 2 så angis altså 1 og to og så angis +, som gir resultatet 3. For å bygge videre på resultatet, angir en nye operander og operatorer, f.eks. regnes (1 + 2) * 3 ut ved å angi sekvensen 1 2 + 3 *. Implementasjonen er svært enkelt, en legger bare operandene på en stack ettersom de angis, og operatorene fjerner og bruker disse og legger resutlatet tilbake.

rpncalc1.py

Nedenfor vises en enkel Python-implementasjon, med forklaringer til høyre.

# rpncalc1.py
operands = []
while (True):
    print(operands)
    token = raw_input(" > ")
    try:
        operand = float(token)
        operands.append(operand)
    except ValueError:
        if (token == "exit"):
            break
        elif (token == "+"):
			operands.append(operands.pop() + operands.pop())
        elif (token == "-"):
            operands.append(operands.pop() - operands.pop())
        else:
            print("Unsupported operator: " + token)
print("program exited")

#-tegnet angir at resten av linja er en kommentar. Akkurat denne brukes her for å angir hvor det er lurt å legge koden.

Tilordningen initialisere operands-variablene til en tom liste med operander.

while-løkka (se while-kontrollstrukturen) brukes for å repetere en blokk med kode, inntil en bestemt betingelse er oppfylt. Her er betingelsen True, dvs. alltid sann, så løkke vil aldri stoppe, med mindre den avbrytes innenfra! Legg forøvrig merke til hvordan en i Python bruker innrykk (mellomrom først på linja) for å angi hvilke setninger som hører til blokken.

print skriver ut operand-stacken, så brukeren ser hva kalkulator-tilstanden er.

raw_input brukes deretter for å lese inn en "noe" fra brukeren, som er er ment å være enten en operand eller en operator.

Først prøver vi inni en try-blokk å gjøre om token, altså det brukeren skrev inn, til et desimaltall. Hvis det går så legges tallet til operands-lista med append, altså bakerst, så det fungerer som en stack.

Dersom konverteringen til desimaltall ikke går, så utløses et ValueError-unntak, som vi håndteres (fanges opp) med except. Vi sjekker da først om programmet skal avsluttes, og så håndterer vi hver operator i en elif-gren (se if-kontrollstrukturen). Her har vi begrenset oss til pluss (+) og minus (-).

For hver av disse operatorene så tas to operander av lista med pop, operasjonen utføres og resultatet legges tilbake med append.

Den siste else-grenen sier fra til brukeren at token ikke ble gjenkjent som operator.

Kjør koden og se at det virker ved å skrive inn ulike operander og operatorer. Vi har plantet (minst) to feil i koden: Den ene har med manglende operander å gjøre, den andre med håndteringen av minus. Prøv å se om du finner en måte å rette dem på, før du leser videre!

Koden over bruker flere variabler for å holde rede på tilstanden til programmet. Den viktigste variablen er operands, som refererer til lista med operander, som utvides og minskes ved gjennomgang av løkka. I tillegg har vi de to variablene token og operand, som holder det brukeren skrev inn som henholdvis (rå)tekst (string) og og konvertert til desimaltall (float). Mens det er viktig at operands-variablen beholder sin verdi for hver runde i løkka, så er det ikke viktig at token og operand gjør det. Tvert imot, så tenker en gjerne at disse er lokale for løkka, selv om Python ikke behandler dem annerledes enn operands i så måte.

La oss se på hvordan variablene hånderes i detalj, når programmet utføres.

rpncalc1Ved oppstart av programmet tanker vi oss at det opprettes et slags notatark, med samme navn som programmet. Fra starten er arket tomt, som vist til venstre.
rpncalc1operands = []Når tilordningen til operands-utføres, så ut noteres navnet og verdien på notatarket.

 

rpncalc2.py

fd

  • No labels