Uke 11 - modules / import / standardbibliotek¶
Eksempler¶
Eksempel 1¶
Vi kan gjenbruke funksjoner og variabler fra en annen fil med import
.
Her er en fil med noe nyttig innhold (du kan laste ned filen her:
eks_1_lib.py
). Sånne filer kalles modul/library:
# Vi kan definere funksjoner...
def fib(n):
"""Return the fibonacci sequence up to n as a list"""
a, b = 0, 1
seq = []
while a < n:
seq.append(a)
a, b = b, a+b
return seq
def collatz(n):
"""Return the collatz sequence from n as a list"""
def collatz_step(n):
if n % 2 == 0:
return n//2
else:
return 3*n + 1
seq = [n]
while n > 1:
n = collatz_step(n)
seq.append(n)
return seq
# ...eller verdier i en bibliotek
# speed of light [m/s]
C_LIGHT = 299792458
# Planck constant [Js]
H_PLANCK = 6.62607015e-34
I hovedprogrammet kan vi gjenbruke filen på ulike måter: Vi kan import
-e hele
filen med sitt navn, eller vi kan gi et nytt navn med import .. as
. Se hvordan
vi bruker funksjoner fra filen.
En annen mulighet er å plukke ut spesifikke funksjoner med from .. import ...
.
Vi kan også bruke as
her. (du kan laste ned hovedprogrammet her:
eksempel_1.py
)
print('Option 1')
import eks_1_lib #import module
fib_1 = eks_1_lib.fib(100)
col_1 = eks_1_lib.collatz(17)
print(fib_1)
print(col_1)
#################################
print('Option 2')
import eks_1_lib as el
print(el.collatz(5))
c = el.C_LIGHT
print(c,'m/s')
#############################
print('Option 3')
from eks_1_lib import fib
fib_2 = fib(75)
print(fib_2)
##############################
print('Option 4')
from eks_1_lib import H_PLANCK as h, C_LIGHT as c, fib
print(c)
print(h)
print(fib(30))
Pass på at begge filene ligger i samme mappen, og at terminalen kjører derfra.
Ved bruk av import kan man strukturere store programmer på en oversiktlig måte, gjerne også i flere mapper. Det går utover pensum her, men mer informasjon finnes på https://docs.python.org/3.8/tutorial/modules.html
Eksempel 2¶
Når du skriver python kode i en fil, finnes det alltid en variabel som heter __name__
.
Verdien til __name__
er __main__
hvis filen kjøres direkte fra terminalen. F.eks hvis man kjører eksempel_2.py
fra terminalen slik: python eksempel_2.py
, så vil variabelen __name__``ha verdien ``__main__
.
Hvis eksempel_2.py
importeres fra en annen python fil, det vil si den blir ikke direkte kjørt fra terminalen, så er variabelen __name__
satt til eksempel_2
, altså navnet på modulen som importerte filen.
Noen ganger vil vi kjøre noe kode i en fil KUN hvis filen blir kjørt direkte, men ikke hvis den blir importert av en annen modul / python fil. For å gjøre dette skriver vi if name == "__main__":
, og putter koden som skal kjøre hvis vi kjører filen direkte fra terminalen innenfor den if-clause.
Last ned eksempel_2.py og kjør filen fra terminalen. Skriver funksjonen hello
ut? Hva er verdien på __name__
?
# if __name__ == "__main__" example
print('This is the top level, or 0 indentation level, of eksempel_2.py')
def hello():
print('hey there')
if __name__ == "__main__":
print('eksempel_2.py is being run directly')
print(f'{__name__} is the value of __name__') #what prints here?
else:
print('eksempel_2.py is being imported')
print(f'{__name__} is the value of __name__') # what prints here?
hello() # we only call function if file is imported
Nå skal vi se hva __name__
er hvis vi kjører python
rett fra terminalen. Åpne en terminal i samme mappe som filen eksempel_2.py
, og skriv python
. Skriv så import eksempel_2
.
Hva skjer nå? Hva er verdien på __name__
? Skriver funksjonen hello
ut denne gangen?
Standardbiblioteker¶
Mange nyttige biblioteker er allerede med i hver Python-installasjon, det er «Python Standard Library». Vi skal vise noen eksempler av nyttige moduler her.
En full oversikt finnes på Pythons hovedsiden: https://docs.python.org/3.8/library/
Når man kommer til å jobbe mer med Python er det lurt å bli kjent med oversikten
her. Man trenger ikke å være ekspert i alle modulene, men man må ha en
idé hva slags moduler det finnes. Moduler som sys
eller os
er brukt i nesten
alle prosjektene, mens biblioteker som f.eks sunau
(Read and write Sun AU audio files)
har en veldig spesialisert målgruppe.
Dokumentasjonen for hvert bibliotek er veldig bra, med mange eksempler. Det finnes alltid noe nyttig når man leser gjennom. Du trenger ikke pugge modulene og bibliotekene vi skal diskutere denne uken. Bruk Python dokumentasjonen som en referanse.
Eksempel 3¶
Pythons bibliotek math
inneholder mange vanlige matematiske funksjoner
og konstanter. Du finner dokumentasjonen for biblioteket på
https://docs.python.org/3.8/library/math.html.
Her er noen eksempler på bruk av math
(du kan laste ned koden her:
eksempel_3.py
):
import math
# The floor and ceiling functions
print(f"{4 / 3}")
print(f"{math.floor(4 / 3)}")
print(f"{math.ceil(4 / 3)}")
print()
# The constant e and powers of it
print(f"{math.e}")
print(f"{math.exp(1)}")
print(f"{math.exp(0)}")
print(f"{math.exp(2)}")
print()
# Logarithms
print(f"{math.log(math.e)}")
print(f"{math.log(1)}")
print(f"{math.log(5)}")
print()
print(f"{math.log2(2)}")
print(f"{math.log2(1)}")
print(f"{math.log2(5)}")
print(f"{math.log2(8)}")
print()
print(f"{math.log10(10)}")
print(f"{math.log10(1)}")
print(f"{math.log10(5)}")
print(f"{math.log10(100)}")
print()
# Exponentials
print(f"{math.pow(2, 3)}")
print(f"{math.pow(2, math.log2(3.3))}")
print(f"{math.pow(4, 1 / 2)}")
print(f"{math.sqrt(4)}")
print(f"{math.sqrt(math.pow(3, 4))}")
# print(f"{math.sqrt(-1)}") # This raises an error
# Use the library 'cmath' for complex numbers
print()
from math import pi
print(f"{pi}")
# The trigonometric functions take input in radians, not degrees
# What should all these values be?
print(f"{math.sin(pi / 2)}")
print(f"{math.sin(pi)}")
print(f"{math.cos(pi / 2)}")
print(f"{math.cos(pi)}")
print(f"{math.tan(pi)}")
print(f"{math.tan(pi / 2)}")
Det finnes også andre bibliotek for å gjøre beregninger. Her er en liste på numeriske biblioteker. Se på noen av dem og lag dine egne eksempler.
Eksempel 4¶
Om man trenger en kalender eller må beregne tidspunkt, er det best å bruke en ferdig bibliotek. I Python er det datetime.
Les gjennom siden og se på eksemplene der.
Filen eksempel_4.py
viser noen enkle bruk av biblioteken:
from datetime import date
today = date.today()
my_birthday = date(today.year, 6, 24)
if my_birthday < today:
my_birthday = my_birthday.replace(year=today.year + 1)
time_to_birthday = abs(my_birthday - today)
print(time_to_birthday)
from datetime import datetime
now = datetime.now()
exam = datetime(2021, 6, 11, 9, 0, 0)
print(exam - now)
Prøv å legge inn noe du fant i dokumentasjonen.
Eksempel 5¶
Når vi vil telle antall kan vi bruke klassen Counter
i biblioteket collections
,
som er en spesiell versjon av dict(), hvor hvert element begynner med 0 allerede.
Dokumentasjonen finner du her:
collections.
Vi prøver igjen
å telle antall ord i en tekst, men denne gangen bruker vi Counter
. Du kan laste
ned koden her: eksempel_5.py
.
from collections import Counter
text = """Alice was beginning to get very tired of sitting by her sister
on the bank, and of having nothing to do: once or twice she had peeped
into the book her sister was reading, but it had no pictures
or conversations in it, 'and what is the use
of a book,' thought Alice 'without pictures or conversation?'"""
letter_count = Counter() # instead of dict() or {}
# Count letters
for let in text:
let = let.lower()
if let in "abcdefghijklmnopqrstuvwxyz":
letter_count[let] += 1
# With Counter we don't have to first create a key for every letter
for let, count in letter_count.items():
print(f"{let} is used {count:3d} times")
print("\n\n\n")
word_count = Counter()
for word in text.split():
word = word.lower()
word_count[word] += 1
# With Counter we don't have to first create a key for every word
# The 5 most used words, Counter has a useful helper function most_common()
# we don't need to sort ourselves
print("The 5 most common words")
print(word_count.most_common(10))
for w, c in word_count.most_common(5):
print(f"{w:14} is used {c:3d} times")
Eksempel 6¶
itertools-biblioteken
gjør det enklere å skrive ulike typer løkke. Filen eksempel_6.py
viser
et tilfelle, men det finnes mange eksempler i dokumentasjonen. Gjerne prøv noen
av dem.
import itertools
print('All DNA triples')
bases = 'ATGC'
# for i in bases:
# for j in bases:
# for k in bases:
# print(i+j+k)
for i,j,k in itertools.product(bases, repeat=3):
print(i+j+k)
Eksempel 7¶
Du kan bruke biblioteket random
til å generere tilfeldige tall. Dokumentasjonen
for dette biblioteket finner du her.
Du kan laste ned koden her: eksempel_7.py
. Prøv å kjør koden noen ganger
uten random.seed(123457)
og noen ganger med random.seed(123457)
. Hva er forskjellen?
import random
# random.seed(123456) # reproduserbare resultater, ulik for hver int
# heltall
print(f"{random.randint(1,6)}") # 1 <= N <= 6
# ulike utvalg fra en sekvens
print(f"{random.choice('abcdef')}")
print(f"{random.choice([11, 7.2, 'foo'])}")
print(f"{random.choices('abcdefghi', k=10)}")
print(f"{random.sample('abcdefghi', k=3)}")
# shuffling
xs = [1, 2, 3, 4, 5, 6, 7, 8, 9]
random.shuffle(xs)
print(f'shuffled 1: {xs}')
random.shuffle(xs)
print(f'shuffled 2: {xs}')
random.shuffle(xs)
print(f'shuffled 3: {xs}')
# float
print(f"{random.random()}") # [0.0, 1.0)
print(f"{random.uniform(12.0, 20.0)}") # 12.0 <= N <= 20.0
print(f"{random.gauss(mu=40.0,sigma=12.0)}")
Oppgaver¶
Oppgave 1¶
I et spill har vi en kortstokk av 10 kort med verdiene [2,3,4,5,6,7,8,9,10,11]
og målet er å samle tre kort med total verdi 21.
Finn og printe alle mulige kombinasjoner av tre kort som har total verdi
21 som sorterte tupler.
Bruk funksjoner fra itertools
Eksempelkjøring:
(2, 8, 11)
(2, 9, 10)
(3, 7, 11)
(3, 8, 10)
(4, 6, 11)
...
Oppgave 2 - datetime, Project Euler nr.19¶
How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
Bruk
datetime
-modulen for å fikseuke11_oppgave_2.py
.Nyttige funksjoner finnes i dokumentasjonen om datetime.date
Oppgave 3 - random¶
(a) Skriv en funksion kast_n_2(n)
som tar inn et heltall n
og
simulerer n kast av
to terninger (random.randint(1,6)
) og legger til summen av de to
i en liste. Returner den listen (som nå inneholder n elementer
med tall mellom 2 og 12).
(b) Hvor ofte får vi øyesummen 2, 3, …, 12? Bruk collections.Counter
i en funksjon print_histo(xs)
som tar inn en slik liste og
printer ut et enkelt histogram hvor '*'
står for 1%.
Pass på formateringen av tallene og mellomrom:
2 **
3 ***
4 *****
...
10 ***
11 **
12 *
(Ikke bruk random.seed() slik at testene kan fungere rett.)
Oppgave 4 - egen statistikk¶
Lag et bibliotek uke11_oppgave_4.py
i den samme mappen sånn at det følgende
programmet fungerer,
men uten å bruke de eksisterende funksjonene mean,median,mode,max,min
fra Python:
import uke11_oppgave_4
data = [3, 1, 7, -3, 5, 9, 1, 5, 9, 7, -3, 7]
a = uke11_oppgave_4.mean(data)
b = uke11_oppgave_4.median(data)
c = uke11_oppgave_4.mode(data)
d = uke11_oppgave_4.max(data)
e = uke11_oppgave_4.min(data)
print(a,b,c,d,e)
Alle funksjonene skal ta én liste som argument.
Funksjonen
mean(xs)
skal returnere gjennomsnittet av tallene i listen. Gjennomsnittet av tallene \(x_1, x_2, ..., x_n\) kan beregnes med formelen:\[\frac{x_1 + x_2 + ... + x_n}{n}.\]For eksempel:
uke11_oppgave_4.mean([2, 5, 3, 1]) # skal returnere 2.75
Funksjonen
median(xs)
skal returnere medianen av tallene i listen. Dette er tallet som er i mitten etter att listen er blitt sortert. Om lengden av listen er jevn er medianen gjennomsnittet av de to tallene i mitten. For eksempel:uke11_oppgave_4.median([4, 12, 3, 9, 5]) # skal returnere 5 uke11_oppgave_4.median([3, 6, 93, 45, 14, 22]) # skal returnere 18
Funksjonen
mode(xs)
skal returnere typetallet: det vanligste tallet i listen. Om flere tall er like vanlige skal funksjonen returnere det tallet som står først i listen. For eksempel:uke11_oppgave_4.mode([3, 4, 22, 7, 4, 15, 4, 7, 1]) # skal returnere 4 uke11_oppgave_4.mode([3, 22, 7, 4, 15, 4, 7, 1, 4, 7, 22, 15, 22]) # skal returnere 22
Funksjonen
max(xs)
skal returnere den største verdien i listen. For eksempel:uke11_oppgave_4.max([3, 6, 93, 45, 6, 14, 22]) # skal returnere 93
Funksjonen
min(xs)
skal returnere den minste verdien i listen. For eksempel:uke11_oppgave_4.min([3, 6, 93, 45, 6, 14, 22]) # skal returnere 3
Oppgave 5 (uten tests)¶
Project Euler 89 er en god
øvelse for dict
og filhåndtering fra uke 10:
For a number written in Roman numerals to be considered valid there are basic rules which must be followed. Even though the rules allow some numbers to be expressed in more than one way there is always a «best» way of writing a particular number.
For example, it would appear that there are at least six ways of writing the number sixteen:
IIIIIIIIIIIIIIII VIIIIIIIIIII VVIIIIII XIIIIII VVVI XVIHowever, according to the rules only
XIIIIII
andXVI
are valid, and the last example is considered to be the most efficient, as it uses the least number of numerals.The 11K text file,
roman.txt
(right click and ’Save Link/Target As…’), contains one thousand numbers written in valid, but not necessarily minimal, Roman numerals; see About… Roman Numerals for the definitive rules for this problem.Find the number of characters saved by writing each of these in their minimal form.
Note: You can assume that all the Roman numerals in the file contain no more than four consecutive identical units.