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