av Peder Bergebakken Sundt og Torje Hoås Digernes
Programvareverkstedets
TODO: TID
TODO: TID
TODO: TID
Det finnes mange implementasjoner og versjoner av python standarden. Vi skal her bruke CPython
Windows og MacOS brukere kan
laste ned Python 3.7 fra nettsiden
Linux og MacOS kan bruke en pakkebehandler
til å installere python3
Implementert av de samme folkene
som bestemmer Python standarden.
Disse to versjonene har noen små forskjeller.
I denne workshoppen vil de nesten ikke merkes.
Workshoppen bruker Python 3.
Python 2 er på vei ut.
Hvis noen her bruker Python 2:
Si ifra! Så peker vi ut forskjellene
IDLE er en enkel teksteditor for
å redigere Python sine .py filer.
Den følger med Python, men er veldig primitiv.
Den har to moduser:
Her skriver man fullverdige python programmer
Programmet kan så kjøres via IDLE eller ved å dobbeltklikke på fila som er lagret
Du skriver og kjører en linje kode av gangen
Skallet gir deg resultatet for hver linje.
Tilstand blir bevart.
>>> 3 + 4
7
>>> print("dette er en test")
dette er en test
>>> print("na" * 8 + ", Batman!")
nananananananana, Batman!
En kompleks kalkulator som utfører
regne- og logikkoperasjonene vi ber den om.
Dette kaller vi instruksjoner
Programmer er ei liste av instruksjoner vi vil datamaskinen skal utføre.
Programmer kan sammenlignes med kokeoppskrifter:
en rekke instruksjoner for kokken å utføre
Et godt definert språk for å formidle
instruksjoner på en måte som
både mennesker og datamaskinen forstår
Python er en av de enkleste og mest brukte
programmeringsspråkene i verden.
Det finnes mange resurser på nettet om
bruk av språket.
Python er brukt mange steder i industrien
import snowy, numpy as np
def create_falloff(w, h, radius=0.4, cx=0.5, cy=0.5):
hw, hh = 0.5 / w, 0.5 / h
x = np.linspace(hw, 1 - hw, w)
y = np.linspace(hh, 1 - hh, h)
u, v = np.meshgrid(x, y, sparse=True)
d2 = (u-cx)**2 + (v-cy)**2
return 1-snowy.unitize(snowy.reshape(d2))
def create_island(seed, freq=3.5):
w, h = 750, 512
falloff = create_falloff(w, h)
ns = sum(
n1 = 1.000 * snowy.generate_noise(w, h, freq*1, seed+0)
n2 = 0.500 * snowy.generate_noise(w, h, freq*2, seed+1)
n3 = 0.250 * snowy.generate_noise(w, h, freq*4, seed+2)
n4 = 0.125 * snowy.generate_noise(w, h, freq*8, seed+3)
elevation = falloff * (falloff / 2 + n1 + n2 + n3 + n4)
mask = elevation < 0.4
elevation = snowy.unitize(snowy.generate_sdf(mask))
return (1 - mask) * np.power(elevation, 3.0)
snowy.save(create_island(10), 'island.png')
Python er et språk som tolkes
av maskinen i sanntid.
Det har dynamiske typer, som betyr
språket ikke er veldig strengt
Du slipper å ta hensyn til så mange smådetaljer som Python håndterer for deg
Python oppmuntrer en ren og oversiktlig kodestil
Hver linje kode inneholder ett eller flere utrykk.
Utrykk er en beregning som returnerer en verdi
>>> 2 + 3
5
>>> 3 * 4
12
>>> sum((1, 2, 3))
6
>>> sqrt(16)
4.0
Vi kan lagre verdier til navn.
Disse navnene kalles variabler.
>>> 2 + 2
4
>>> hei = 2 + 2
>>> hei
4
>>> hei = hei + 2
>>> hei
6
>>> hei * 2
12
Vi kan skrive kommentarer i koden for
å forklare og hjelpe oss med å holde oversikt.
# Dette er en kommentar
# De fleste teksteditorer har grønne kommentarer
# IDLE viser kommentarer i rødt
a = 1 # kommentarer går til slutten av linja
# a = 2
print(a) # Dette vil skrive ut 1 til brukeren
Vi kan "kommentere ut" kode som ikke brukes
Python bruker indentering (innrykk) for å separere
kode inn i "blokker". Dette brukes i flytkontrol og
funksjoner, som vi dekker i dag.
import random
# Denne "if" strukturen har to blokker:
if random.random() > 0.5:
print("Hei")
else:
print("Hallo")
out = []
# de to neste linjene tilhører denne "for" løkken
for i in range(5):
i_squared = i**2
out.append(i_squared)
print(sum(out))
For å kunne utføre aritmetikk og logikk,
trenger vi operatorer å regne med:
>>> 3 + 4 # plusse sammen tall
7
>>> 3 - 4 # trekke to tall fra hveradre
-1
>>> 3 * 4 # gange sammen tall
12
>>> 3 / 4 # dele to tall på hverandre
0.75
Et par mer avanserte operatorer:
>>> 2 ** 3 # to opphøyd i tredje
8
>>> 10 % 3 # Modulo: Resten av 10 delt på 3
1
Disse brukes ikke ofte og kan raskt oppsøkes på nettet etter behov
>>> 2 > 3 # større enn
False
>>> 2 < 3 # mindre enn
True
>>> 4 >= 4 # lik eller større
True
>>> 4 <= 4 # lik eller mindre
True
>>> 2 == 3 # lik
False
>>> 2 != 3 # ulik
True
>>> 4 == 4 # lik
True
>>> a = 1
>>> b = 2
>>> a == b # sammenlikning
False
>>> a = b # tilordning, bemerk ingen returverdi
>>> a == b # sammenlikning
True
>>> a
2
>>> b
2
== og = er to forskjellige operatorer!
Python vil av og til hindre deg i å gjøre denne feilen
Operatorene har en definert rekkefølge,
likt som i matematikken:
>>> 1 + 3 * 4
13
>>> (1 + 3) * 4
16
Den er for det meste intuitiv, men kan
overstyres med parenteser
"and" og "or" brukes til å kombinere sammenlikninger:
#
>>> True and True
True
>>> True and False
False
>>> False and True
False
>>> False and False
False
>>> True or True
True
>>> True or False
True
>>> False or True
True
>>> False or False
False
Lag et uttrykk som sjekker om en
ukjent verdi er mellom 4 og 10
>>> a = 3 # definer verdien a
>>> a == 5 # kjør uttrykket
False
>>> a = 5# endre a til en ny verdi
>>> a == 5 # kjør uttrykket på nytt
True
Tips:
Trykk ALT+P for å kopiere forrige linje kjørt i IDLE.
Trykk gjentatte ganger for eldre linjer
Trykk opp-tasten istedet hvis du bruker terminal
>>> a = 3
>>> 4 <= a and a <= 10
False
>>> a = 5
>>> 4 <= a and a <= 10
True
>>> a = 12
>>> 4 <= a and a <= 10
False
Utgangspunkt
Løsning
>>> a = 1
>>> b = 2
>>> a > b
False
>>> a > b or b > a
True
>>> False or True
True
Programmer trenger en måte å ta beslutninger,
og kunne tilpasse handlingene sine ut ifra disse.
>>> a = 2
>>> b = 3
>>> if a == b:
... print("equal")
... else:
... print("not equal")
...
not equal
Blokken under kodeordet "if" kjøres kun hvis utrykket
evalueres til True
>>> if False:
... print("something happened")
>>> if True:
... print("something happened")
something happened
>>>
Blokken under "else" kjøres kun hvis blokken under
det tilsvarende "if" kodeordet ikke ble kjørt
>>> if True:
... print("The if block was run")
... else:
... print("The else block was run")
...
The if block was run
>>> if False:
... print("The if block was run")
... else:
... print("The else block was run")
...
The else block was run
"elif" er en forkortelse for "else: if"
"elif" lar oss teste flere muligheter på en enkel måte:
if a == 1:
print("one")
else:
if a == 2:
print("two")
else:
if a == 3:
print("three")
else:
print("unknown")
if a == 1:
print("one")
elif a == 2:
print("two")
elif a == 3:
print("three")
else:
print("unknown")
Lag et program som tar inn et testresultat
mellom 0 og 100, og skriver ut en tilsvarende
karakter mellom A og F
Utgangspunkt:
(Finn opp mengden poeng som bestemmer
de ulike karakterene)
# Skriv dette som ei fil med IDLE
# (trykk File -> New File eller CTRL+N hvis du er i skallet)
# Husk å lagre fila!
from random import random
result = round(100*random()) # en verdi mellom 0 og 100
print(result)
Lag et program som tar inn et testresultat
mellom 0 og 100, og skriver ut en tilsvarende
karakter mellom A og F
Løsningsforlsag:
from random import random
result = round(100*random()) # en verdi mellom 0 og 100
print(result)
if result >= 90:
print("A")
elif result >= 80: #trenger ikke teste om result er under 90
print("B")
elif result >= 70:
print("C")
elif result >= 60:
print("D")
elif result >= 50:
print("E")
else:
print("F")
Verdier kan være av forskjellige typer
Typen bestemmer hvordan informasjonen blir
lagret i minne og behandlet av operasjoner.
>>> type(5)
<class 'int'>
>>> type(5.0)
<class 'float'>
>>> type("Hei på deg")
<class 'str'>
Boolske verdier betegner sannheter.
De fleste sammenlikninger evalueres til en boolverdi
>>> True
True
>>> if True: print("test")
...
test
>>> if False: print("test")
...
>>> 3 > 2
True
Bool brukes i "if" spørringer
Heltall blir lagret som typen "int", kort for "integer"
Desimaltall blir lagret som typen "float": flyttall
>>> type(5) # heltall er av typen "integer"
<class 'int'>
>>> type(5.0) # flyttall er av typen "float"
<class 'float'>
Med Python 3 trenger du for det meste ikke bry deg om forskjellen mellom float og int.
Tekst er lagret i form av strenger, kalt "str" i python
(programmerere likte korte navn på 90 tallet)
>>> 'test' == "test" # typen fnutter er ikke viktig
>>> "hei " + "på " + "deg!" # strenger kan kombineres
'hei på deg!'
>>> "ha" * 3 # strenger kan bli gjentatt
'hahaha'
>>> type("hei")
<class 'str'>
Ei liste kan inneholde flere elementer av
arbitrere typer
>>> mylist = [123, 456, 789]
>>> mylist[0] # indekser starter på 0
123
>>> mylist[1]
456
>>> mylist.append("hei") # lister kan endres
>>> mylist
[123, 456, 789, 'hei']
>>> mylist[1:3] # lister støtter "slicing"
[456, 789]
Den største gotcha'en med lister er nullindeksering.
De fleste programeringsspråk bruker dette
Python kaller ordbøker "dict", kort for dictionary.
Ordbøker "oversetter" fra en verdi til en annen:
fra en nøkkel til verdi
>>> mylist = [5, 6, 7]
>>> mylist[1] # fra lister henter vi verdier via indeksen
6
>>> mydict = {"hei":1, "hallo":"min verdi"}
>>> mydict["hei"] # oppslag gjøres med en "nøkkel", ikke via indeks
1
>>> mydict["hallo"]
'min verdi'
>>> mydict[33] = "ny verdi" # du kan legge inn nye verdier
>>> mydict
{'hei': 1, 'hallo': 'min verdi', 33: 'ny verdi'}
>>> mydict["hei"] = 2 # eller overskrive eksisterende verdier
>>> mydict
{'hei': 2, 'hallo': 'min verdi', 33: 'ny verdi'}
De forskjellige typene oppfører seg forsjellig
for de ulike operatorene.
>>> 2 + 2 # + betyr addering for tall
4
>>> "a" + "a" # + betyr sammenslåing for strenger
'aa'
>>> 2 + "a" # her kan ikke python bestemme seg for oppførsel
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
De fleste typer har en eller annen form for "sannhet"
>>> bool(0) # integer 0 er usann-aktig
False
>>> bool(1) # alle andre heltall er sanne
True
>>> bool(99)
True
>>> bool(-1)
True
>>> bool([]) # tomme lister er usanne
False
>>> bool([1, 2]) # lister med innhold er sanne
True
>>> bool("") # tomme strenger er usanne
False
>>> bool("hei") # strenger med innhold er sanne
True
De fleste typer er "usanne" hvis de er tomme
"tuple" fungerer på samme måte som "list",
men de er "immutable": De kan ikke bli endret på.
>>> foo = [1, 2, 3] # liste
>>> foo.append(99)
>>> foo
[1, 2, 3, 99]
>>> bar = (1, 2, 3) # tuple
>>> bar.append(99)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'
"There would only exists about 5 good programmers in the world, if it where not for Google."
Funksjoner tar null eller flere verdier
inn og returnerer en verdi
>>> abs(3) # absoluttverdi
3
>>> abs(-3)
3
>>> max([5, 7, 2])
7
>>> min([5, 7, 2])
2
Du "kaller" funksjonen "foo" ved å skrive:
>>> foo()
Python: "batteries included"
Moduler er "samlinger" eller "biblioteker"
med ferdige funksjoner og verdier
som du kan importere og ha nytte av
>>> import math # hente modulen "math"
>>> math.pi # bruke verdien "pi" i "math"
3.141592653589793
>>> math.sqrt(25) # square root
5.0
Det følger med mange moduler med python.
Det finnes også mange moduler du kan
laste ned fra nettet og bruke i ditt program
Vi er ikke tvungen til å hente inn hele modulen:
Det kan være kortere å hente kun enkelte funksjoner.
>>> import math
>>> math.sqrt(16)
4.0
>>> from math import sqrt
>>> sqrt(16) # trenger skrive ikke "math."
4.0
vs
De fleste mener den siste er mer "ryddig"
Du trenger man ikke pugge alle nå,
men det er fint å vite at de eksisterer.
Google er din venn fra nå av.
Returnerer absoluttverdien til et tall
>>> abs(-2)
2
>>> abs(-1)
1
>>> abs(0)
0
>>> abs(1)
1
>>> abs(2)
2
Ikke veldig nyttid i det interaktive skallet, men
veldig nyttig i større programmer
navn = input("Hva heter du? ") # spør om tekst fra brukeren
print("Hei " + navn + "!") # skriver tekst ut til brukeren
Print støtter flere parametre, som blir
slått sammen med en separator (mellomrom):
navn = "Robert"
print("Hei på deg", navn)
print(1, 2, 3)
print(1, 2, 3, sep="-") # endrer separator til en strek
Hei på deg Robert
1 2 3
1-2-3
min og max returnerer det minste
og det største elementet i ei liste
>>> mylist = [2, 2, 3, 1, 4, 0, 2]
>>> max(mylist)
4
>>> min(mylist)
0
Du kan bruke funksjonen "sorted" til å lage en
sortert kopi av ei liste
>>> mylist = [2, 2, 3, 1, 4, 0, 2]
>>> sorted(mylist)
[0, 1, 2, 2, 2, 3, 4]
>>> mylist
[2, 2, 3, 1, 4, 0, 2]
>>> mylist2 = [[3,"a"], [2, "b"], [1, "c"]] # ei liste av lister
>>> sorted(mylist2) # listene sorteres i leksikal rekkefølge
[[1, 'c'], [2, 'b'], [3, 'a']]
Skriv et program som spør brukeren om tre tall.
Skriv de ut igjen i sortert rekkefølge
mylist = [
int(input("Tall 1: ")),
int(input("Tall 2: ")),
int(input("Tall 3: "))
]
print(sorted(mylist))
De fleste typer har en eller flere funksjoner
som oversetter en verdi fra en type til en annen:
>>> a = "123"
>>> type(a)
"<class 'str'>"
>>> int(a) # oversette strengen til heltall:
123
>>> type(int(a))
"<class 'int'>"
age = int(input("Hvor gammel er du? "))
Du får en flyt-verdi du vil runde ned til nærmeste heltall
mitt_tall = 55.3
# din kode her
print(mitt_tall) # dette skal skrive ut 55
mitt_tall = 55.3
mitt_tall = int(mitt_tall)
print(mitt_tall) # dette skal skrive ut 55
round() avrunder et flyttall til det nærmeste heltallet
>>> round(2.0)
2
>>> round(2.3)
2
>>> round(2.8)
3
>>> int(2.8)
2
Datamaskinen må gjøre avrundinger
grunnet et begrenset antall siffer.
Dette blir rart for oss, fordi maskinen lagrer tall som
binærtall (0 og 1) , og ikke de desimaltallene vi forventer:
>>> 0.1*3 # binær avrunding
0.30000000000000004
>>> round(2.5) # merk at round() ikke alltid runder opp ved 0.5
2
>>> # dette er fordi 0.5 ikke kan
>>> # representeres nøyaktig med 0 og 1
Disse småfeilene er sjeldent av stor betydning.
map() kjører en gitt funksjon på hvert element i ei liste,
og returnerer ei ny liste med alle resultatene
>>> mylist = [-3, -2, -1, 0, 1, 2, 3]
>>> map(abs, mylist)
<map object at 0x7fa5f3aaa748>
>>> list(map(abs, mylist)) # oversette "map object" til ei liste
[3, 2, 1, 0, 1, 2, 3]
>>> list(map(str, mylist))
['-3', '-2', '-1', '0', '1', '2', '3']
"map object" kommer vi til å snakke om senere
En modul med en rekke kule matte funksjoner og verdier
>>> import math
>>> math.pi
3.141592653589793
>>> math.factorial(5)
120
>>> 1*2*3*4*5
120
>>> math.factorial(int(input("Give a number: ")))
Give a number: 6
720
Google: "python math module"
for ei fin oversikt over funksjonene og verdiene i modulen
Brukes for å se på filer i filsystemet
Resten av os modulen har
mange andre kule formål
>>> import os.path
>>> filnavn = "C:/Users/Bob/min_fil.txt"
>>> os.path.dirname(filnavn)
'C:/Users/Bob'
>>> os.path.basename(filnavn)
'min_fil.txt'
>>> os.path.exists(filnavn)
True
>>> os.path.isdir(filnavn)
False
>>> os.path.isfile(filnavn)
True
>>> from datetime import date
>>> today = date.today()
>>> today.isoformat() # ISO 8601 standardformatet
'2018-08-30'
>>> my_birthday = date(today.year, 2, 20) # 20. februar
>>> if my_birthday < today:
... my_birthday = my_birthday.replace(year=today.year + 1)
...
>>> my_birthday.isoformat()
'2019-02-20'
>>> time_to_birthday = abs(my_birthday - today)
>>> time_to_birthday.days
174
Google vet mer
For å introdusere tilfeldige valg
>>> import random
>>> random.random() # tilfeldig tall mellom 0 og 1
0.14072062696326082
>>> random.random()
0.47548683533973257
>>> random.random()
0.940841472800279
>>> random.choice([1, 2, 3])
3
>>> random.choice([1, 2, 3])
2
>>> random.choice([1, 2, 3])
1
>>> random.choice([1, 2, 3])
2
Disse trenger du ikke pugge.
Bare vit at sannsynligheten for at det du trenger
allerede finnes som en modul er stor.
Google er din venn.
Brukes for å lese og skrive excel dokumenter
>>> import csv
>>> with open('eggs.csv', newline='') as csvfile:
... spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
... for row in spamreader:
... print(', '.join(row))
Spam, Spam, Spam, Spam, Spam, Baked Beans
Spam, Lovely Spam, Wonderful Spam
Det finnes et "enklere" alternativ: Pandas
Pandas må lastes ned. Vi kommer til å snakke mer om Pandas på del 2 av kurset.
Brukes for å hente og sende data til og fra nettsider
>>> import urllib3
>>> http = urllib3.PoolManager()
>>> resp = http.request('GET', 'http://www.vg.no/robots.txt')
>>> print(resp.data.decode("utf-8"))
user-agent: Googlebot-News
disallow: /annonsorinnhold/
disallow: /innstikk/
Det finnes et "enklere" alternativ: requests
requests må lastes ned, men er enklere å bruke. Google har mange fine guider.
Brukes for å kjøre funksjoner i parallel "tråder"
from concurrent.futures import ThreadPoolExecutor
import shutil # brukes til å håndtere filer
with ThreadPoolExecutor(max_workers=4) as e:
e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
e.submit(shutil.copy, 'src4.txt', 'dest4.txt')
Ofte må vi installere python moduler vi har behov for.
En ofte brukt modul er requests:
Denne prosessen kan variere fra platform til platform
Morgendagens kurs kommer til å gå igjennom tre viktige biblioteker for databehandling i stor detalj:
Ikke alt er innebygd i Python. Du kan lage egne
funksjoner og redusere mengden koden du må skrive
def input_int(prompt): # prompt er input argument
return int(input(prompt))
#return brukes for å returnere en verdi
print(input_int("Gi et nummer: ") * 2)
Gi et nummer: 5
10
Funksjoner kan ta inn et vilkårlig antall parametre/argumenter inn:
def min_kule_funksjon(arg1, arg2, arg3):
print("Jeg fikk", arg1, arg2, "og", arg3, "inn!")
min_kule_funksjon(1, 2, 3)
min_kule_funksjon("hei", "på", "deg")
Jeg fikk 1 2 og 3 inn!
Jeg fikk hei på og deg inn!
Funksjoner kan returnere en verdi
def tail(liste):
return liste[1:]
#summerer alle tallene i liste med unntak av første element:
mylist = [4, 4, 3, 3]
print(sum(tail(mylist))) # skriver ut tallet 10
Lag en funksjon som bestemmer om
et tall er odde eller ikke
Utgangspunkt:
def is_odd(number):
pass
print("5 is odd:", is_odd(5)) # Skal skrive False
print("6 is odd:", is_odd(6)) # Skal skrive True
print("7 is odd:", is_odd(7)) # Skal skrive False
None er en spesiell verdi. Funksjoner som ikke returnerer en verdi vil returnere None
>>> def i_do_nothing():
... pass # python krever kode i hver blokk. Pass gjør ingenting
...
>>> i_do_nothing()
>>> foo = i_do_nothing()
>>> print(foo)
None
>>> None # Det interaktive skallet skuler None
>>> 1 # andre verdier skrives ut
1
Lister og tupler kan "pakkes ut" til variabler
>>> a, b, c = (1, 2, 3)
>>> a
1
>>> b
2
>>> c
3
>>> 1, 2, 3 # python velger tuple hvis ingen parenteser presiseres
(1, 2, 3)
>>> a, b, c = "hei", "på", "deg"
Vi kan utnytte "unpacking" til å returnere flere verdier
def my_function(value):
return value*2, value/2
a, b = my_function(4)
print(a) # Skriver ut 8
print(b) # Skriver ut 2.0
Noen parametre kan ha et standardvalg satt.
Disse kalles også "named parameters"
def min_kule_funksjon(arg1, arg2, foo=1, bar=2):
print(arg1, arg2, foo, bar)
min_kule_funksjon(1, 2) # skriver ut: 1 2 1 2
min_kule_funksjon(1, 2, 3) # skriver ut: 1 2 3 2
min_kule_funksjon(1, 2, 3, 4) # skriver ut: 1 2 3 4
min_kule_funksjon(1, 2, bar=4) # skriver ut: 1 2 1 4
Gitt to variabler, bytt verdiene på de
Utgangspunkt:
a = 1
b = 2
# din kode her
print(a, b) # dette skal skrive ut 2 1
a, b = b, a
temp = a
a = b
b = temp
Det finnes mye annet også
Det finnes mange funksjoner for å
behandle strenger i Python
>>> min_hilsen = "Hei " + "på " + "deg!"
>>> min_hilsen
'Hei på deg!'
>>> min_hilsen.lower() # oversetter bokstavene til små bokstaver
'hei på deg!'
>>> min_hilsen.upper() # oversetter bokstavene til store bokstaver
'HEI PÅ DEG!'
>>> "petter".capitalize()
'Petter'
>>> min_hilsen = "Hei " + "på " + "deg!"
>>> min_hilsen
'Hei på deg!'
>>> min_hilsen[0] # indeksering
'H'
>>> min_hilsen[1]
'e'
>>> min_hilsen[2]
'i'
>>> min_hilsen = "Hei " + "på " + "deg!"
>>> min_hilsen
'Hei på deg!'
>>> min_hilsen[:5] # Implisitt fra starten
'Hei p'
>>> min_hilsen[5:] # implisitt til slutten
'å deg!'
>>> min_hilsen[2:6] # eksplisitt start og slutt
'i på'
Slicing fungerer på samme måte for elementene i lister
>>> min_hilsen = "Hei " + "på " + "deg!"
>>> min_hilsen
'Hei på deg!'
>>> min_hilsen.split() # "split" deler strengen opp i ei liste av ord
['Hei', 'på', 'deg!']
>>> min_hilsen.split()[:-1]
['Hei', 'på']
>>> "".join(["a", "b", "c"]) # "join" samler ei liste av strenger
'abc'
>>> " test ".join(["a", "b", "c"]) # separatoren kan bestemmes
'a test b test c'
>>> "#".join(min_hilsen.split())
'Hei#på#deg!'
split er ofte brukt til å tolke strenger.
join er nyttig for å konstruere strenger fra elementer.
Skriv et program som tar inn ei setning fra brukeren
og som skriver ut ordene i sortert rekkefølge.
sentence = input("Input a sentence: ")
words = sentence.split()
words = sorted(words)
output = " ".join(words)
print(output)
Bytter ut alle instanser av en søkestreng med
en annen annen strenge, og returnerer en ny kopi.
>>> min_strenge = "Hei på deg!"
>>> min_strenge.replace("Hei", "halla")
'halla på deg!'
>>> min_strenge.replace("å", "aa")
'Hei paa deg!'
>>> min_strenge.replace("Hei", "Hei'du").replace("deg", "deg'du")
"Hei'du på deg'du!"
>>> min_strenge # merk den originale er ikke endret.
'Hei på deg!'
Python har en rekke forskjellige måter å
formatere strenger på. De fleste bruker
"format" eller f-strenger:
>>> str(1) + " og " + str(2) # manuelt og tungvindt
'1 og 2'
>>> "{} og {}".format(1, 2) # positional
'1 og 2'
>>> "{a} og {b}".format(b=2, a=1) # named
'1 og 2'
>>> a = 1
>>> b = 2
>>> "{a} og {b}".format(**locals()) # named from local namespace
'1 og 2'
>>> f"{a} og {b}" # shorthand, called f-strings
'1 og 2'
>>> f"{a} og {b+3}" # which supports expressions
'1 og 5'
Python og de fleste andre språk støtter
"escape" koder for å spesifisere spesielle tegn i strenger.
I python bruker vi "backslash" for escape koder.
>>> print("hei\npå\ndeg!") # \n betyr newline
hei
på
deg!
>>> print("Dette er et hjerte: \u2764") # alle unicode tegn er støttet
Dette er et hjerte: ❤
>>> print("For å skrive en backslash \\")
For å skrive en backslash \
>>> print("For å skrive en fnutt: \" ")
For å skrive en fnutt: "
Vi kan ikke lære alle funksjonene på en dag.
Let rundt på Google etterhvert som behovene
dukker opp, og lær etter behov!
if og else er kult, men ikke spesielt kraftig.
Med løkker kan vi kjøre ei blokk
med kode gjentatte ganger!
>>> for i in [1, 2, 3]:
... print("Element", i)
...
Element 1
Element 2
Element 3
"for" løkken itererer gjennom en liste og kjører
blokken med kode for hvert element i lista.
"for each item in x, do the following"
>>> for i in [1, 2, 3]:
... print("The double of", i, "is", i*2)
...
The double of 1 is 2
The double of 2 is 4
The double of 3 is 6
Ta inn ei liste av mellomromm-separerte tall og
skriv ut hvert tall fordobblet.
Eksempelkjøring:
numbers = input("Skriv inn liste av tall: ")
for number in numbers.split():
print(int(number) * 2)
Skriv inn liste av tall: 1 2 3
2
4
6
blokken under while vil fortsette å kjøre
så lenge utrykket i while er sant.
"do that while this is true"
>>> value = 2
>>> while value < 10000:
... value = value*2
...
>>> value
16384
Lag en meny som gir brukeren valg mellom noen funksjoner og muligheten til å avslutte programmet.
Menyen skal "gjenta" seg frem til brukeren avslutter.
Eksempelkjøring:
Velg enten foo, bar eller stop
Valg: foo
Dette er foo
Velg enten foo, bar eller stop
Valg: bar
Dette er bar
Velg enten foo, bar eller stop
Valg: foo
Dette er foo
Velg enten foo, bar eller stop
Valg: stop
Avslutter...
def foo():
print("Dette er foo")
def bar():
print("Dette er bar")
stop = False
while not stop:
print("Velg enten foo, bar eller stop")
valg = input("Valg: ")
if valg == "foo":
foo()
elif valg == "bar":
bar()
elif valg == "stop":
stop = True
else:
print("Jeg forstår ikke")
print() # tom linje
print("Avslutter...")
while kan kjøre uendelig, er du uheldig
>>> while True:
... print("This is not a good idea")
...
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
This is not a good idea
Hvis dette skjer kan du som regel stoppe programmet ved å trykke CTRL+C,
eller lukke vinduet, eller via CTRL+ALT+DELETE
er du uheldig
range er en funksjon som lager ei liste med tall i serie
Merk: nullindeksering
>>> range(10)
range(0, 10)
>>> list(range(10)) # oversette til liste for lestbarhet
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for i in range(10):
... print("Verdien av i er", i)
...
Verdien av i er 0
Verdien av i er 1
Verdien av i er 2
Verdien av i er 3
Verdien av i er 4
Verdien av i er 5
Verdien av i er 6
Verdien av i er 7
Verdien av i er 8
Verdien av i er 9
range støtter flere argumenter, som er med
på å bestemme hvordan den skal lage lista
>>> list(range(3, 7))
[3, 4, 5, 6]
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(2, 10))
[2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(2, 10, 3))
[2, 5, 8]
>>> list(range(10, 0, -1))
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Skriv et program som beregner summen av
alle kvadrattall fra 1² til 15²
summen av 1 + 4 + 9 + 16 + ... + 225
sum = 0
for n in range(1, 16):
sum += n * n
print(sum) # skriver ut 1240
numbers = []
for i in range(1, 16):
numbers.append(i * i)
print(sum(numbers))
Ikke bare tupler og lister har elementer i seg.
Det er mange typer og objekter som
inneholder flertall elementer.
Hvis typen er "iterable", kan du iterere
over elementene med en for løkke:
>>> val = range(3)
>>> val
range(0, 3)
>>> type(val) # verdien er av typen "range"
"<class 'range'>"
>>> for i in val: print(i)
...
0
1
2
list() vil hente alle elementene fra en iterable
og konstruere ei liste fra den.
Det samme gjelder tuple()
>>> val = range(3)
>>> val
range(0, 3)
>>> list(val)
[0, 1, 2]
>>> tuple(val)
(0, 1, 2)
Generatorer er en type iterable, som beregner
den neste verdien i det øyeblikket Python spør om den.
range() er en generator. Den lager ikke hele lista, med elementer, den lager bare et element av gangen.
Dette tillater:
# Ei liste med alle disse elementene ville brukt mer minne
# enn datamaskinen har tilgjengelig
for i in range(9999999999999999999999999999999999999999):
print(i)
Vi kan iterere manuelt med iter() og next()
Dette viser jeg frem bare for forståelsen
>>> iterable = range(3)
>>> iterator = iter(iterable)
>>> next(iterator)
0
>>> next(iterator)
1
>>> next(iterator)
2
>>> next(iterator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> mylist = [1, 2, 3]
>>> for i in mylist:
... mylist.append(i)
... print(i)
...
1
2
3
1
2
3
1
2
3
1
Mange vil påstå att den største
styrken til python er listeutrykk.
Listeutrykk produserer en generator.
Denne generatoren kan vi lage ei liste av
>>> exp = (i * 2 for i in range(5))
>>> exp # exp er en generator
<generator object <genexpr> at 0x7fb6ae445f48>
>>> list(exp)
[0, 2, 4, 6, 8]
>>> (i * 2 for i in range(5)) # generatoren
<generator object <genexpr> at 0x7fd66f3dff48>
>>> [i * 2 for i in range(5)] # rett til liste
[0, 2, 4, 6, 8]
Listeutrykkene
>>> out = []
>>> for x in range(5):
... for y in range(5):
... if x > y:
... out.append( x + y )
...
>>> out2 = [x+y for x in range(5) for y in range(5) if x>y]
>>>
>>> out == out2
True
Lag et program som filtrerer bort
de tallene i ei liste som er større en 10
ved hjelp av listeutrykk
Utgangspunkt:
mylist = list(range(20))
print(list(...))
mylist = list(range(20))
print(list(i for i in mylist if i <= 10))
Skriv et program som beregner summen av
alle kvadrattall fra 1² til 15²
(dvs: summen av 1 + 4 + 9 + 16 + ... + 225)
ved hjelp av listeutrykk.
>>> sum(i*i for i in range(1, 16))
1240
Av og til er if og else blokker litt for mye å skrive.
De kan gjøres inline:
>>> for i in (-1, 2, 6, -7):
... print(i, "er", "positiv" if i>=0 else "negativ")
...
-1 er negativ
2 er positiv
6 er positiv
-7 er negativ
To måter å gjøre samme jobben:
De fleste som liker Python synes
listeutrykk er enklere å forstå.
Map kan gi høyere ytelse
>>> mylist = [1, 2, 3, 4, 5]
>>> def double(x):
... return x * 2
...
>>> [double(i) for i in mylist]
[2, 4, 6, 8, 10]
>>> list(map(double, mylist))
[2, 4, 6, 8, 10]
Skriv et program som beregner alle fibonaccitallene:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55....
a, b = 0, 1
while True:
print(a)
a, b = b, a+b
Lag et program som skriver ut tallene fra 1 til 100,
men alle tall som er delbar på 3 erstattes med "fizz",
og tall delbar på 5 erstattes med "buzz".
Hvis delbar på begge: "fizzbuzz"
>>> for i in (1, 2, 3, 4, 5, 6, 7):
... print(i, "% 3 ==", i%3)
...
1 % 3 == 1
2 % 3 == 2
3 % 3 == 0
4 % 3 == 1
5 % 3 == 2
6 % 3 == 0
7 % 3 == 1
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
Eksempel
output
Nyttig forkunnskap
for i in range(1, 101):
if i % 15 == 0:
print("fizzbuzz")
elif i % 3 == 0:
print("fizz")
elif i % 5 == 0:
print("buzz")
else:
print(i)
print("\n".join(
"fizzbuzz" if i%15==0 else
"fizz" if i%3==0 else
"buzz" if i%5==0 else
str(i)
for i in range(1,101)))
print(*("fizz"*(i%3==0) + "buzz"*(i%5==0) or i
for i in range(1,101)), sep="\n")
Et palindrom er det samme om man leser fra
høyre eller fra venstre. Det største palindromet
laget av produktet av to tosifrede heltall er:
9009 = 91 x 99
Lag et program som finner det største palindromet
som er et produkt av to tresifrede tall.
biggest = 0
for x in range(1, 1000):
for y in range(1, 1000):
if str(x*y) == str(x*y)[::-1]:
if x*y > biggest:
biggest = x*y
print(biggest)
all_products = (x*y for x in range(1, 1000) for y in range(1, 1000))
def is_palindrome(num):
return str(num) == str(num)[::-1]
print(max(i for i in all_products if is_palindrome(i)))
#skriver ut 906609
Python kan lese fra og skrive til filer.
Å lese filer kan være nyttig for databehandling.
handle = open("myfile.txt", "r") # åpne i "read" modus
data = handle.read()
handle.close() # lukke filhåndtaket
# "data" er en strenge som inneholder hele filen
print(data)
Vi kan lese fila linje for linje:
# "with" kjører file.close() for oss når vi er ferdig
with open("myfile.txt", "r") as file:
for line in file:
print(line)
Dette er grunnen til å huske å lukke filer.
Bruk "with"!
Python kan skrive data til filer.
result = []
for i in range(10):
result.append( i * 2 )
with open("output_file.txt", "w") as file:
for i in result:
file.write(str(i)) # krever at data er en strenge
file.write("\n") # husk linjeskift!
Enkelte handlinger i Python er ugyldige.
Disse vil oftest resultere i en
feilmelding som stopper programmet
>>> 5 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> foo = 3
>>> foo
3
>>> fooo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'fooo' is not defined
Disse kalles "Exceptions"
Når en Exception intreffer vil Feilmeldingen
fortelle deg hva som gikk feil og hvor feilen skjedde
Traceback (most recent call last):
File "hei.py", line 7, in <module>
print(foo(99))
File "hei.py", line 2, in foo
return bar(my_number * 2 + 3)
File "hei.py", line 5, in bar
return my_number / 0
ZeroDivisionError: division by zero
# hei.py
def foo(my_number):
return bar(my_number * 2 + 3)
def bar(my_number):
return my_number / 0
print(foo(99))
Traceback
Kode
Når en Exception blir hevet, stanser programmet
1
2
Traceback (most recent call last):
File "hei.py", line 4, in <module>
1 / 0
ZeroDivisionError: division by zero
# hei.py
print(1)
print(2)
1 / 0
print(3)
print(4)
Konsoll
Kode
For å forhindre programstans kan vi "fange" Exceptions.
Til dette har vi "try" og "except" nøkkelordene:
def dangerous_function(input):
a = input + 3
b = input - 3
return a / b
try:
print(dangerous_function(1))
print(dangerous_function(2))
print(dangerous_function(3))
print(dangerous_function(4))
except ZeroDivisionError:
print("Someone divided by zero")
print("Still running!")
-2.0
-5.0
Someone divided by zero!
Still running!
Konsoll
Kode
Det er fristende å "gjemme" feil, men dette gjør
det vanskelig å "debugge" koden: å fikse feil.
Dette vil forhindre tracebacks, og
oppmuntrer ustabil kode.
Ikke gjem feilen, håndter den!
try:
my_dangerous_function()
except:
pass # ignore it
# todo: fix this later
print("Everything is fine") # it isn't
En try-except trenger ikke håndtere alle feil.
De burde kun håndtere de feilene som er forventet.
value = None
while value == None:
try:
value = int(input("Enter a number: "))
except ValueError: # int() hever denne feilen
print("Not a valid number!")
# Denne blokkerer ikke MemoryError f.eks,
# som heves når maskinen er tom for RAM
print("The double is:", value*2)
None
Unngå å returner None når funksjonen din feiler.
Da må de som bruker funksjonen huske å sjekke mot dette.
Det er bedre å heve en exception
Se under Ressurser
Beginner Python Excercises
eller
Du leser kode oftere enn du skriver kode.
Hold koden ryddig og forstålig.
Skriv kommentarer!
Bruk fornuftige variabel- og funksjonsnavn.
Prøv å kjør dette:
>>> import this