Uke 5 - Skop og fillesing

Husk: Dette dokumentet er kun for hjelp, det er forelesningsfoilene og pensumsboka som bestemmer pensum og læringsmål. Om noe her motstrider med det som er gjennomgått i forelesning, si ifra til meg (sondrbw@uio.no), og følg det som forelesningen sier.

Stikkord for timen

  • skop
  • input/output

Forskjeller på funksjon, prosedyre og metode (repetisjon fra sist)

Funksjon

En funksjon som defineres med def, som ikke er del av en klasse (ordet self brukes ikke). Funksjoner har alltid en returverdi. Eks:

def sum(a, b):
    c = a + b        
    return c

På engelsk kalles dette function.

Prosedyre

Tilsvarende funksjon, men uten returverdi. Bruker aldri ordet self, og er ikke del av en klasse. Eks:

def superprint(ord):
        print("ordet er", ord)

På engelsk kalles dette procedure.

Metode

Tilsvarende funksjon, men som del av en klasse. Har alltid self som første parameter. Kan, men må ikke, ha en returverdi. Eks:

def areal(self):
        firkant_areal = self.lengde * self.bredde
        return firkant_areal

På engelsk kalles dette method.

NB!

Frem til vi lærer mer om objekter er det kun funksjoner og prosedyrer vi fokuserer på.

 

Sende med parametere (repetisjon fra sist)

  • Til prosedyrer/funksjoner kan man også sende med parametre, som er en type variabler. Variablene man sender med “blir” de som er med som argument i prosedyren.

Syntaks:

def prosedyre_navn(parameter1, parameter2, ...)  # kan ha så mange parametere man vil
    <gjøre ting>

F.eks.

def summer(a, b):
    print("sum: ", a + b)

Inni prosedyren “summer” vil a her ha verdien 5 og b ha verdien 6. Man kan også sende med variabler når man kaller på en prosedyre: Feks.

z = 7
y = 3.5
summer(z, y)

Her vil a få verdien 7 og b får verdien 3.5.

NB! Når prosedyren summer er ferdig så vil ikke a og b “beholde” verdiene sine. Repetere igjen; Fordel med prosedyrer -> kan gjenbruke kode! Kan kalle på en prosedyre flere ganger

Tegn opp disse kallene, forklar hvordan a og b får sine “verdier”.

Parametrene som sendes med kan være hvilke som helst verdier.

 

Med returverdi - funksjoner:

I eksemplene fra forrige uke skrev vi ut verdiene.

Noen ganger ønsker man metoder som i stedet for å skrive ut noe, returnerer noe til oss (gjerne basert på parametrene vi sender med) som vi kan bruke videre i programmet.

Syntaks:

def funksjons_navn(parameter1, parameter2, ...)  # kan ha så mange parametere man vil
    <gjøre ting>
    return <returverdien>

Eks.

def summer(a, b):
    sum = a + b # i stede for å skrive ut så regner vi sammen summen og lagrer i variabelen “sum”.
    return sum  # deretter returnerer vi verdien til sum.

Slik kaller vi funksjonen:

verdi_fra_summer = summer(2, 3)

NB! En funksjon kan kun returnere én ting(!).

Dersom man ønsker å returnere mer enn 1 ting må man lage en liste, legge tingene i listen og returnere hele listen. Som regel når man kaller en funksjon tar man vare på verdien den returnerer med en variabel.

 

Hva får vi hvis vi nå skriver ut verdi_fra_summer?

print(verdi_fra_summer)
 

Oppgave 1

  1. Skriv en funksjon som tar i mot to tall og returnerer det største av de to tallene (ikke skrive det ut).

  2. Lag en main prosedyre som kaller på funksjonen din

In [1]:
def storst_av_to(tall1, tall2):
    if tall1 < tall2:
        return tall2
    return tall1

def main():
    sum = storst_av_to(2, 3)
    print(sum)
    
main()
Utskriften her blir:
3
 

Skop

“Skop” vil si den delen av programmet du kan aksessere/få tilgang på variabler, altså det man "ser". En variabel som er definert i en prosedyre kalles for en “lokal variabel”. Defineres variabler utenfor en prosedyre vil den være en “global variabel” og dermed tilgjengelig for alle.

Generelt burde man bruke lokale variabler og heller lage prosedyrer som returnerer verdier fremfor globale variabler som oppdateres av mange prosedyrer.

Gitt koden som beregner gjennomsnittet under her:

def gjennomsnitt(tall1, tall2):
    snitt = (tall1 + tall2)/2
    return snitt

gjennomsnitt(2,6)
print(tall1)

Vil variablene tall1 og tall2 kun eksistere inne i funksjonen gjennomsnitt.

Det vil si at det f.eks. ikke er mulig å skrive ut tall2 etter linjen gjennomsnitt(2,6)

 

Skop er viktig

Skop er veldig viktig, siden det sier noe om hva deler av programmet “ser”.

Vi fortsetter med det første eksempelet:

def summer():
    print("sum: ", a + b)   

a = 3
b = 2
summer()

Å skrive det på denne måten går fint, da benyttes verdiene til a og b til summeringen. Her er a og b globale variabler. (dette kommer vi tilbake til)

Vi skriver om på den:

def minus(): 
    a = 3
    b = 2

def summer():
    print("sum: ", a + b)

summer()

Og ser at vi får utskriften under og at dette ikke går. Hvorfor går ikke dette?

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-2-b301b183cc38> in <module>
      6         print("sum: ", a + b)
      7 
----> 8 summer()
      9 # Dette går ikke fordi a og b ikke eksisterer i skopet til summer

<ipython-input-2-b301b183cc38> in summer()
      4 
      5 def summer():
----> 6         print("sum: ", a + b)
      7 
      8 summer()

NameError: name 'a' is not defined
Dette går ikke fordi a og b ikke eksisterer i skopet til summer.
 

Filer og tekster

Av og til ønsker vi å lese eller skrive noe til fil. Når vi skal bruke filer, enten lese fra dem eller skrive til dem, må vi åpne og lukke dem.

Når vi åpner filen må vi også bestemme hva vi skal kunne gjøre med den.

Åpne fil

Syntaks: Lese en fil:

innfil = open("filnavn.filtype", "r")   # “r” står for “read”

Eksempel: Gitt at det finnes en fil som heter “input.txt”, hvis vi skal lese den skriver vi:

innfil = open("input.txt", "r")# åpner fila

For å kunne skrive til en fil må vi gjøre:

utfil = open("filnavn.fitype", "w") # w står for “write”

For å kunne skrive til ved å legge til:

utfil = open("filnavn.filtype", "a")    # a står for  “append”

Lese fra fil

linje = innfil.readline()

.readline() vil lese en linje fra oppgitt fil som en String, her lagres denne string-verdien i variabelen “linje”.

Lukke fil

innfil.close()  # lukker når man er helt ferdig med filen.
    utfil.close()

Altså:

  1. Åpne filen
  2. Gjør det du skal med fila (lese/skrive)
  3. Lukk filen

Eksempel

Eks. tenk at test.txt består av følgende linjer:

Hei!
Dette er en fil

Så for å lese fila test.txt skriver vi følgende kode:

innfil = open("test.txt", "r")
linje = innfil.readline()   # første linje i filen leses, dvs. “Hei!”

Når denne så lagres i variablen “linje” lagres den som Hei!\n (\n = newline, linjeskift.)

Når det ikke lenger er noe innhold i filen, dvs. Tom linje (“ ”), så leses dette som “\n" av filleseren.

Om vi ønsker å skrive til fil. (sjekk boken kap 7/side 386 om du interessert i dette.) Syntaks:

 utfil.write(“Skriv dette til fil\n”)

Og når vi er ferdig med filen må vi huske å lukke den.

innfil.close()    # lukker når man er helt ferdig med filen.
utfil.close()
 

Minieksemepel: lese alle linjene i filen

linje = innfil.readline()
while linje != "" : # lese helt frem til tom linje/slutten av filen
    # <gjøre noe med variabelen “linje”/det som er lest inn>
    linje = innfil.readline() # lese neste linje i filen, repeter while-løkken

Er også mulig å løse denne med

for linje in fil:
    # gjør noe med "linje"/det som er lest inn
 

Oppgave 2

Anta at du har filen “historie.txt”. Les inn alle linjene og lagre dem i en liste. Første linje skal ligge først i listen, osv.

(Tips: husk å åpne og lukke filen..)

Løsningsforslag alternativ 1:

fil = open("historie.txt", "r")

linjeliste = []

for linje in fil:
    linjeliste.append(linje)

print(linjeliste)  

Alternativ med bruk av while.

fil = open("historie.txt", "r")

linjeliste = []

linje = fil.readline()
linjeliste.append(linje)
while linje != "":
    linje = fil.readline()
    linjeliste.append(linje)
    
print(linjeliste)  

Konvertere til tall:

Når man leser en linje fra en fil så leses det som string, dersom man ønsker å konvertere til tall skriver man

verdi = float(linje)    # konverterer til flyttall/float
verdi = int (linje) # konverterer til heltall/int

, \n vil da ignoreres

 

Oppgave 3

Skriv en funksjon som tar i mot to sannhetsverdier (True/False) og returnerer 1 hvis begge verdier er sanne, 0 hvis begge verdier ikke er sanne.

Gruble: Hva tar ikke funksjonen høyde for? Hva kan gå “galt”?

def funksjon(a, b):
    if a and b:
        return 1
    if not (a and b):
        return 0
Denne funksjonen tar ikke høyde for hva som kan skje om a og b er ulike.

Her er en ekstra oppgave der vi bruker løkker, lister/ordbøker funksjoner og ser på fordeler med skop.

# Lag en funksjon:
# om du har to lister med verdier (som er like lange)
# [False, True, False, True, False]
# [False, False, False, True, False]

# returner en liste som dette:
# [0, 0, 0, 1, 0]
# Altså, der en av de er False 0, der begge er True 1, om listene har ulik lengde returner -1


def funksjon(a, b):
    """En metode som tar inn to parametere og returnerer 1 om begge er sanne, 0 om begge er sanne"""
    if a and b:
        return 1
    else:
        return 0

def tainnto(liste1, liste2):    
    assert len(liste1) == len(liste2)
    
    nyListe = []
    
    # går igjennom begge listene
    for i in range(len(liste1)):
        var = funksjon(liste1[i], liste2[i])
        nyListe.append(var)
    return nyListe
        
lst1 =  [False, True, False, True, False]
lst2 = [False, False, False, True, False]

nylst = tainnto(lst1,lst2)
print(nylst)
Utskriften her blir:
[0, 0, 0, 1, 0]
Publisert 14. okt. 2020 20:53 - Sist endret 14. okt. 2020 20:56