Göm menyn

Satser och uttryck

Det här avsnittet handlar om satser och uttryck som är beståndsdelarna i Python-program. Här följer vårt första riktiga Python-program (som gör något).

Newton-Raphson

Newton-Raphson är en algoritm som uppskattar kvadratroten av ett tal. En matematisk förklaring av algoritmen finns i slutet av dokumentet.

Implementation

def find_root():
    """ Prints the approximation of the square root of a given number """
    print("This program tries to find the square root of a number ")
    x = int(input("Enter a number: "))
    guess = x / 2
    for i in range(5):
        guess = (guess + x / guess) / 2
        print(guess)

Vi ska använda oss av detta program för att visa de olika delarna som Python-program består av.

Så vad gör programmet egentligen?

  • Programmet består av en enda funktion, find_root.
  • Rad nummer 2 är en så kallad kommentar som är till för oss som läser koden, den påverkar inte programmets körning
  • Programmet börjar med att skriva ut en förklaring till användaren.
  • Programmet läser in en rad från användaren och försöker tolka vad som matades in och sparar detta i variabeln x. En variabel låter programmet associerar ett namn, x i det här fallet, till ett värde, i det här fallet det användaren matat in.
  • Programmet gissar sedan att roten ur x är x/2 och sparar gissningen i variablen guess.
  • Det upprepar sedan raderna i for-loopen (koden under for i in range(5): ...) fem gånger, detta är ett exempel på repetition.
  • För varje varv i upprepningen så räknar den ut en bättre gissning, updaterar variabeln guess samt skriver ut den i terminalen.

Varför mellanrum?

Underordnande rader måste skjutas in en bit på raden, vilket kallas indenteras. Detta är för att Python ska förstå att dessa rader hör till find_root.

Satser - ryggraden i ett imperativt program

Ett Python-program består av ett antal satser (eng. statements) som utförs i tur och ordning. Satser gör något. Vi ska titta på de fem viktigaste där vi redan har sett de fyra första.

Enkla satser

  • Tilldelning (eng. assignment), t.ex. x = x + 2
  • Funktionsanrop, t.ex. print("hello")

Dokumentation

Sammansatta satser

  • Iteration med for, t.ex. for i in range(5): ...
  • Funktionsdefinition, t.ex. def find_root(): ...
  • Selektion med if, t.ex. if a > 0: ...

Dokumentation

Olika typer av satser

Tilldelning

Tilldelning fungerar på följande sätt:

namn = uttryck

Det som händer är att uttryck beräknas, det vill säga att värdet på högerledet bestäms, och resultatet sparas i den namngivna variablen. I vårt exempel find_root görs tilldelning på flera ställen, bland annat på rad 4. Där tilldelar vi variabeln guess resultatet av beräkningen x/2.

Funktionsanrop

Funktionsanrop ser ut på följande sätt:

funktionsnamn(argument, argument2, ...)

En funktion kan ta inget, ett eller flera argument (... betyder att det kan finnas fler argument). Argument används för att överföra information från den som anropar en funktion till funktionen.

Det som händer är att argumenten (som är uttryck) beräknas och skickas till funktionen, underprogrammet som behandlar datan.

Funktionsanrop kan även användas i sammansatta uttryck då en funktion alltid returnerar ett värde även om den används som en sats. Har funktionen ingen explicit retur-sats så returneras None.

Till exempel så har vi funktionsanrop på rad 3 i find_root, där vi anropar funktionerna eval och input. Här sätts variabeln x till resultatet från anropet till funktionen eval som i sin tur tar resultatet från anropet till funktionen input.

Iteration med for

Iteration, det vill säga upprepning av en grupp satser, ser ut på följande sätt:

for namn in område:
    ...
    ...
    ...

Det som händer är att gruppen av satser inuti for-satsen, även kallat undersatser, körs så många gånger som området specificerar. område kan t.ex. vara en lista med värden som variabeln namn ska ta. För varje så kallad iteration så updateras namn.

I exemplet ovan finns en for-sats på rad 5. Funktionen range(n) returnerar en så kallad generator som motsvarar en lista bestående av sekvensen 0, 1, ..., n-1. Alltså kommer for-satsen att köra fem iterationer eller varv och för varje varv kommer den öka variabeln i med 1. Variabeln börjar med värdet 0. Det betyder att i första iterationen är i=0, i andra är i=1, och i den femte och sista iterationen är i=4.

Funktionsdefinition

En funktionsdefinition definierar en funktion, det vill säga en grupp av satser med ett namn så att de enkelt kan anropas senare.

En funktionsdefinition ser ut på följande sätt:

def funktionsnamn(parameter1, parameter2, ...):
    ...
    ...
    ...

I exemplet har vi exakt en funktionsdefinition, find_root, som inte har några parameterar. En parameter kan ses som en variabel som funktionen kan använda och som får sitt värde av ett argument i funktionsanropet.

Selektion

Selektion eller villkorssatser är satser som kör en grupp satser beroende på det givna villkoret. De kallas också för if-satser.

En if-sats inleds med en if, följt av noll eller flera elif och avslutas med noll eller en else.

Villkorssatser i Python kan se ut på följande sätt:

# Ett alternativ
if a > 0:
    print("positivt")

# Två alternativ
if a >= 0:
    print("icke-negativt")
else:
    print("negativt")

# Tre eller fler alternativ
if 0 <= a < 10:
    print("ental")
elif a < 0:
    print("negativt")
else:
    print("tio eller mer")

Uttryck - värdefulla saker

Uttryck (eng. expressions) är delar av satser som kan beräknas till ett värde, t.ex. ett tal eller en bit text.

Dokumentation

Än så länge har vi i huvudsak stött på följande typer av uttryck:

Enkla uttryck

Identifierare

När Python ser en identifierare (ett namn) så som x eller find_root så kommer den att försöka slå upp värdet i dess interna symboltabell. Uttryckets värde blir sedan det värde som Python funnit i tabellen. Om identifieraren inte finns i tabellen skriver programmet ut ett felmeddelande och avbryts.

Literaler

Literaler eller konstanter är värden och till skillnad från identifierare så kan deras värde aldrig ändras. I vårt program har vi literaler på flera ställen, bland annat så är "Enter a number: " en literal, lika så är talen 2 och 5 literaler.

Sammansatta uttryck

Sammansatta uttryck är precis vad det låter som; ett uttryck bestående av flera uttryck.

De förekommer bland annat på formen:

deluttryck_a operator deluttryck_b

Värdet av ett sammansatt uttryck bestäms av att operatorn tar emot argumenten, det vill säga deluttrycken, och utför någon beräkning eller operation på dem.

I exemplet är t.ex. (guess + x / guess) / 2 ett sammansatt uttryck med operatorerna + och /. Parenteserna talar om för Python i vilken ordning operationerna ska utföras.

Funktionsanrop

Även funktionsanrop är ett sammansatt uttryck. I exemplet så har vi range(5) och eval(input("Enter a number: ")) som uttryck då de båda returnerar ett värde.

Uppbygnad av ett program

I grunden ser ett program ut på följande sätt:

sats1
sats2
sats3
...

Sats1 kan till exempel vara en funktionsdefinition, så som find_root. Vi kollar hur det är uppbyggt:

def find_root():
    undersats1
    undersats2
    undersats3
    ...

sats2
sats3
...

Vi kan nu utveckla undersatserna i find_root för att se hur de ser ut.

def find_root():
    print("This program tries to find ...")
    undersats2
    undersats3
    ...

sats2
sats3
...

Vi fortsätter att utveckla undersatserna.

def find_root():
    print("This program tries to find ...")
    x = uttryck1
    undersats3
    ...

sats2
sats3
...

Uttryck1 är i detta fall ett funktionsanrop till eval.

def find_root():
    print("This program tries to find ...")
    x = eval(uttryck2)
    undersats3
    ...

sats2
sats3
...

Uttryck2 är i sin tur ett funktionsanrop till input.

def find_root():
    print("This program tries to find ...")
    x = eval(input(uttryck3))
    undersats3
    ...

sats2
sats3
...

Uttryck3 är här literalen "Enter a number: " som skickas som argument till input.

Sats eller uttryck?

Undrar man huruvida något är ett uttryck kan man testa att skriva in det vid Python-prompten. Om den skriver ut ett värde kan man som tumregel säga att det är ett uttryck. Notera att sådana uttrycksatser fungerar bra i interpretatorn, men kommer inte att göra något inne i funktioner.

Extra: Matematisk förklaring av Newton-Raphson

Vi visar hur man approximerar kvadratroten av 2 med hjälp av algoritmen.

Vi börjar med att göra en approximation x = 3/2 (= 1.5). Kvadrerar vi x får vi 9/4, vilket är större än 2.
Alltså är:

2/x = 4/3, och (2/x)^2 = 16/9 vilket är mindre än 2. Alltså är:

Tar vi genomsnittet av dessa två:

Kvadrerar vi y får vi samma samband:

y är alltså en närmre approximering än x.

Tar vi åter igen genomsnittet av y och 2/y får vi ett värde som är ännu närmre det sökta värdet

Tillhörande quiz

Finnes här


Sidansvarig: Peter Dalenius
Senast uppdaterad: 2021-12-03