Operatorer

Kategori Operatorer
Aritmetikk **
* / // %
+ -
Relasjoner == != < <= > >= in not in is is not
Logikk not
and
or
Betingelse ... if ... else ...

Aritmetikk med tall

Symbolene + - * / ** utfører henholdsvis addisjon, subtraksjon, multiplikasjon, divisjon og eksponentiering med to tall.

Alle operatorene fungerer likt for både heltall (int) og flyttall (float), men merk at divisjon / alltid returnerer et flyttall, selv om resultatet numerisk sett er et heltall.

print(6 + 2) # 8
print(6 - 2) # 4
print(6 * 2) # 12
print(6 / 2) # 3.0
print(6 ** 2) # 36
print(36 ** 0.5) # 6.0 (en eksponent på 0.5 er det samme som kvadratrot)
Aritmetikk med strenger
# Strenger repeteres flere ganger med gangesymbol (*) og et heltall
print("bar" * 2) # barbar
# Strenger konkateneres (limes sammen) med pluss (+)
a = "foo"
b = "bar"
c = a + b
print(c) # foobar
Heltallsdivisjon og modulo

Heltallsdivisjon med restverdi er den første formen for divisjon vi lærte på barneskolen. La oss si at du skal fordele 14 gullmynter på 4 pirater: da kan hver pirat få 3 gullmynter, og så blir det 2 gullmynter til overs. Vi kan uttrykke regnestykket i Python ved å benytte operatorene for heltallsdivisjon (//) og modulo (%) slik:

coins = 14
pirates = 4
coins_per_pirate = coins // pirates
remainder = coins % pirates

print(coins, "gullmynter skal fordeles på", pirates, "sjørøvere.")
print("Hver sjørøver får da", coins_per_pirate, "gullmynter",
      "og det blir", remainder, "mynter til overs.")

Heltallsdivisjon er som vanlig divisjon, men runder alltid nedover.

print("Operatøren / utfører vanlig divisjon")
print(" 7 / 4  =", (7/4))  # 1.75
print()
print("Operatøren // utfører heltallsdivisjon:")
print(" 7 // 4 =", ( 7//4)) # 1 (runder nedover)
print("-1 // 4 =", (-1//4)) # -1 (runder også nedover)
print("-7 // 4 =", (-7//4)) # -2 (runder også nedover)
print("Når nevneren er negativ")
print(" 7 // -4 =", (7//-4)) # -2 (runder også nedover)
print("-7 // -4 =", (-7//-4)) # 1 (runder altså alltid nedover uansett)

Modulo-operatoren (%) returnerer «resten» etter heltallsdivisjon. Vi kan bruke dette for å avgjøre om et tall er delelig med et annet (hvis resten er 0, er det delelig).

print(8 % 3) # 2
print(7 % 3) # 1
print(6 % 3) # 0    6 er delelig med 3
print(5 % 3) # 2
print(4 % 3) # 1
print(3 % 3) # 0    3 er delelig med 3
print(2 % 3) # 2
print(1 % 3) # 1
print(0 % 3) # 0    0 er delelig med 3
print(-1 % 3) # 2
print(-2 % 3) # 1
print(-3 % 3) # 0   -3 er delelig med 3
print(-4 % 3) # 2
print(-5 % 3) # 1
print(-6 % 3) # 0   -6 er delelig med 3

En annen vanlig bruk av modulo er å finne siste siffer i et tall:

print(123 % 10) # 3
print(1234 % 10) # 4
print(12345 % 10) # 5

En siste vanlig bruk av modulo, er for å få en verdi til å «gå i ring», eller holde seg innenfor et visst intervall. For eksempel, la oss si at vi ønsker at en viss variabel alltid skal befinne seg innenfor intervallet 0-400. Da kan vi bruke modulo-operatoren til å «wrappe» verdien tilbake til intervallet dersom den skulle komme utenfor:

x = 385

...

x = (x + 10) % 400
print(x) # 395 (som forventet når vi gjør 385 + 10)

...

x = (x + 10) % 400
print(x) # tilbake til 5 i stedet for 405, fordi 405 % 400 blir 5
Sammenligning av verdier

Relasjons-operatorene benyttes for å sammenligne to verdier, og resulterer alltid i en boolsk verdi (enten True eller False).

print("== sammenligner om to verdier er like")
print(2 == 2) # True
print(2 == 3) # False
print(2 == 2.0) # True
print("foo" == 'foo') # True
print("foo" == "bar") # False
print()

print("!= sammenligner om to verdier er ulike")
print(2 != 2) # False
print(2 != 3) # True
print(2 != 2.0) # False
print("foo" != 'foo') # False
print("foo" != "bar") # True
print("< sammenligner om venstre side er «mindre enn» høyre side")
print(2 < 3) # True
print(2 < 2) # False
print(2 < 1) # False
print("foo" < "barbar") # False (sammenligner «ASCII-alfabetisk»)
print("foo" < "foo") # False
print("barbar" < "foo") # True 
print()

print("<= sammenligner om venstre side er «mindre enn eller lik» høyre side")
print(2 <= 3) # True
print(2 <= 2) # True
print(2 <= 1) # False
print("foo" <= "barbar") # False (sammenligner «ASCII-alfabetisk»)
print("foo" <= "foo") # True 
print("barbar" <= "foo") # True

Operatorene > og >= fungerer likt som < og <=, men med motsatt fortegn.

Flyttall og avrundingsfeil

Se også videoen Floating point numbers av Computerphile.

print(0.1 + 0.1 == 0.2)        # True, men...
print(0.1 + 0.1 + 0.1 == 0.3)  # False! 
print(0.1 + 0.1 + 0.1)         # gir 0.30000000000000004 (oj sann!)
print((0.1 + 0.1 + 0.1) - 0.3) # gir 5.55111512313e-17 (lite, men ikke 0!)

Derfor: Ikke bruk == for å sammenligne flyttall! Sjekk i stedet at de to tallene som sammenlignes er nesten like.

def almost_equals(a, b):
    epsilon = 0.0000000001
    return abs(a - b) < epsilon # abs()-funksjonen gir absolutt-verdien

print(0.1 + 0.1 + 0.1 == 0.3)  # Feil
print(almost_equals(0.1 + 0.1 + 0.1, 0.3))  # Riktig
Medlemskap

Operatorene in og not in brukes for å sjekke om en verdi er medlem av en liste, tuple, mengde eller streng.

# Sjekk om symboler finnes i strenger
print("a" in "abc") # True
print("d" in "abc") # False
print("A" in "abc") # False ("A" og "a" er forskjellige symboler)

print("a" not in "abc") # False
print("d" not in "abc") # True
print()

print("bc" in "abc") # True
print("ac" in "abc") # False (selv om både "a" og "c" er i "abc")
# Sjekk om en verdi finnes i en liste eller ikke
print(1 in [1, 2, 3]) # True
print(4 in [1, 2, 3]) # False
print(1 not in [1, 2, 3]) # False
print(4 not in [1, 2, 3]) # True
# Sjekk om en verdi finnes i en tuple eller ikke
print(1 in (1, 2, 3)) # True
print(4 in (1, 2, 3)) # False
print(1 not in (1, 2, 3)) # False
print(4 not in (1, 2, 3)) # True
# Sjekk om en verdi finnes i en mengde eller ikke
print(1 in {1, 2, 3}) # True
print(4 in {1, 2, 3}) # False
print(1 not in {1, 2, 3}) # False
print(4 not in {1, 2, 3}) # True
Logiske operatorer

Logiske operatorer bruker vi for å kombinere boolske verdier. De tre logiske operatorer er and, or og not.

print("and returnerer True hvis begge leddene er True")
print(True and True) # True
print(True and False) # False
print(False and True) # False
print(False and False) # False
print()

print("or returnerer True hvis minst ett av leddene er True")
print(True or True) # True
print(True or False) # True
print(False or True) # True
print(False or False) # False
print()

print("not returnerer motsatt boolsk verdi")
print(not True) # False
print(not False) # True

Det er vanlig å benytte logiske operatorer for å binde sammen flere uttrykk som hver for seg evaluerer til boolske verdier.

age = 2000
if (age < 0) or (age > 130):
    print("I find it quite hard to believe you're", age, "years old!")
Uttrykk med betingelse (if else)
print("Foo" if True else "Bar") # Foo
print("Foo" if False else "Bar") # Bar
print("Foo" if 1 < 2 else "Bar") # Foo
print()

x = -3
print(0 if x < 0 else x) # 0 (fordi -3 < 0 er True)
Presedens og assosiativitet

En av de aller vanligste feilene som gjøres (f. eks. på eksamen) er at man gjør feil antakelse om hvilken rekkefølge operatorer i et uttrykk utføres i; hvordan de «usynlige parentesene» i uttrykket er plassert.

Presedens

For aritmetikk gjelder de samme presedens-reglene som er vanlig i matematikk.

print("Presedens:")
print(2 + 3 * 4)  # gir 14, ikke 20   ( * har høyere presedens enn + )
print(5 + 4 % 3)  # gir  6, ikke 0    ( % har høyere presedens enn + )
print(2 ** 3 * 4) # gir 32, ikke 4096 (** har høyere presedens enn * )

I tabellen øverst på denne siden er operatorene sortert etter presedens (det vil si, ** har høyeste presedens mens ... if ... else ... har den laveste). Operatorer i samme rad har samme presedens (for eksempel har + og - samme presedens).

Det er operatorene med høyest presedens som utføres «først» med mindre parenteser indikerer noe annet.

Assosiativitet

Dersom flere operasjoner med samme presedens forekommer i samme uttrykk, utføres de som hovedregel fra venstre til høyre.

print("Assosiativitet: venstre til høyre")
print(5 - 4 - 3)  # det samme som (5 - 4) - 3, altså -2 (ikke 4)
print(9 // 3 // 3) # det samme som (9 // 3) // 3, altså 1 (ikke 9)

Det finnes likevel noen unntak:

Parenteser

Parenteser vil alltid overstyre presedens og assosiativitet. Det er god stil å bruke parenteser for å vise hvilken rekkefølge du ønsker at operatorene utføres i, selv om det ikke alltid er nødvendig – det gjør koden din mer lesbar og mindre utsatt for feil som skyldes at du ikke husker presedenstabellen.

Eksempler

Under er det noen eksempler hvor det er fort gjort å feiltolke hvordan uttrykket evalueres fordi det ikke er angitt parenteser. Bruk reglene for presedens og assosiativitet kombinert med presedensrekkefølgen for operatorene gitt i tabellen øverst på siden og prøv å forutsi hva hvert uttrykk evaluerer til før du kjører koden og ser fasiten.

print(True or True and False) 
print(not False or True)
print(not (False or True))
print()
print(2 < 3 < 4)
print(not 3 < 2 < 1)
print(not 3 < 2 and 2 < 1)
print()
print("b" in "box")
print("b" in "box" == True) # (Brython/nettleser krasjer, men prøv i python)
print("a" and "b" in "box")
print("a" or "z" in "box")

Moralen i historien: benytt parenteser for å vise hva du mener. Det er fort gjort å huske feil rekkefølge, og du kan heller ikke forvente at dine kolleger og ditt fremtidige jeg (som senere skal vedlikeholde koden) husker den.