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: :download:`eks_1_lib.py`). Sånne filer kalles modul/library: .. literalinclude:: eks_1_lib.py 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: :download:`eksempel_1.py`) .. literalinclude:: eksempel_1.py 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__``? .. literalinclude:: eksempel_2.py 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: :download:`eksempel_3.py`): .. literalinclude:: eksempel_3.py 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. .. .. fractions?? .. https://docs.python.org/3.8/library/fractions.html 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 :download:`eksempel_4.py` viser noen enkle bruk av biblioteken: .. literalinclude:: eksempel_4.py 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 <../uke_09/#eksempel-4>`_ å telle antall ord i en tekst, men denne gangen bruker vi ``Counter``. Du kan laste ned koden her: :download:`eksempel_5.py`. .. literalinclude:: eksempel_5.py Eksempel 6 .......... `itertools `_-biblioteken gjør det enklere å skrive ulike typer løkke. Filen :download:`eksempel_6.py` viser et tilfelle, men det finnes mange eksempler i dokumentasjonen. Gjerne prøv noen av dem. .. literalinclude:: eksempel_6.py Eksempel 7 .......... Du kan bruke biblioteket ``random`` til å generere tilfeldige tall. Dokumentasjonen for dette biblioteket finner du `her `_. Du kan laste ned koden her: :download:`eksempel_7.py`. Prøv å kjør koden noen ganger uten ``random.seed(123457)`` og noen ganger med ``random.seed(123457)``. Hva er forskjellen? .. literalinclude:: eksempel_7.py 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 å fikse :download:`uke11_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 :math:`x_1, x_2, ..., x_n` kan beregnes med formelen: .. math:: \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 XVI However, according to the rules only ``XIIIIII`` and ``XVI`` 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, :download:`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.