• No results found

TDDE44 Programmering, grundkurs

N/A
N/A
Protected

Academic year: 2022

Share "TDDE44 Programmering, grundkurs"

Copied!
110
0
0

Loading.... (view fulltext now)

Full text

(1)

TDDE44 Programmering, grundkurs

Föreläsning 3.1-3.2

Jody Foo, jody.foo@liu.se

(2)

Föreläsning 3.1 & 3.2

⁃ Återkoppling från Laboration 2

⁃ Laboration 3: En egen pokedex data från webben

⁃ Oföränderliga och föränderliga värden

⁃ Referenser

⁃ Ny datatyp: dictionary

⁃ Mer om dataabstraktion

⁃ Nästlade datastrukturer

⁃ Bearbetning av nästlade datastrukturer

⁃ Rekursion

(3)

Återkoppling från laboration 2

⁃ När ska while- resp. for-loop användas?

⁃ Namngivning av variabler och funktioner

mönster, t.ex. for word in words undvik för generella namn

⁃ shebang-raden

⁃ Windows

py istället för python

ange encoding när textfil öppnas

(4)

for- loop eller while-loop?

# for-loopar är bra på att iterera genom sekvenser utan att vi behöver

# ta hand om en massa logistik for value in values:

if value == 42:

print("I found the answer!")

# du inte ta hand om någon logistik vid användning av for-loop i = 0

for value in values:

if value == 42:

print("I found the answer!") i += 1

Onödigt

(5)

for- loop eller while-loop?

import random

# while-loopar är bra om man vill fortsätta loopa under vissa

# förutsättningar - villkor

hemligt_ord = random.choice(["apelsin", "banan", "citron"]) gissat_ord = None

antal_försök = 0

while gissat_ord != hemligt_ord:

if gissat_ord != None:

print("Fel!")

gissat_ord = input("Gissa vilket ord jag tänker på: ") antal_försök += 1

print("Rätt! Det tog " + str(antal_försök) + " försök.")

(6)

Namngivning av funktioner och variabler

⁃ Försök att använda beskrivande funktions- och variabelnamn. Koden blir lättare att läsa.

⁃ Använd verbliknande namn för funktioner

add_numbers() , calculate_volume() , load_file() ,

find_most_common_word()

⁃ Använd substantiv till variabelnamn.

⁃ Bra att döpa listor till substantiv i plural: words , values ,

names

⁃ Mönster vid användning av for-loop:

for word in words

(7)

Python-skript och shebang- raden

För exekverbara textfiler i Linux, om första raden börjar på #!

(hash bang → shebang) kommer skalet att anta att efterföljande text på raden är sökvägen till den programtolk som ska

användas på resten av filen

⁃ Bash-skript

#!/bin/bash

⁃ Python-skript

#!/usr/bin/env python3

⁃ Perl-skript

#!/usr/bin/perl

(8)

Python och windows

⁃ Om man installerar Python i Windows installeras hjälpprogrammet py

⁃ py gör att shebang-rader också fungerar i windows

⁃ Vissa har märkt att de kan använda py för att köra python-

filer, men inte python3

(9)

Laboration 3

Del 1: Pythonuppgifter 3

Del 2: Egen Pokedex; hämta information från

webben

(10)

Kort om laboration 3, Del 2

⁃ Hämta information från webben istället för från fil

⁃ Nytt textbaserat data-format: JSON

⁃ Webb-API:er - om URL:er vore funktioner

⁃ PokeAPI - ett webb-API till en databas om Pokémon

⁃ pokedex.py - skript som skriver ut information om en pokémon.

⁃ Lektion 3: övningar inför Del 2

paketet requests för att hämta data från webben

JSON-data till dictionary

(11)

Oföränderliga och föränderliga värden

eng. immutable, mutable

(12)

Oföränderliga värden

⁃ I Python är strängar, heltal, flyttal, sanningsvärden, None och tupler oföränderliga (eng. immutable).

⁃ Detta betyder att man inte kan ändra på dessa värden.

t.ex. så kan inte ändra värdet 5 till värdet 1 , värdet 5 är alltid 5 .

Python behandlar strängar på samma sätt; i Python kan vi inte

ändra strängen "hej" till strängen "nej"

(13)

Oföränderliga värden

⁃ Datatypen tuple fungerar som en lista, förrutom att man inte kan byta dess element.

⁃ Parenteser används för att skapa en tuple .

l = [1, 2, 3] # lista l[0] = 5

l → [5, 2, 3]

t = (1, 2, 3) # tupel

t[0] = 5 → TypeError

(14)

Föränderliga värden

⁃ Av de datatyper som vi stött på så är tillhör listor och dictionaries (som vi stöter på strax) kategorin

förändringsbara värden (eng. mutable).

⁃ Detta betyder att vi kan ändra på dessa värden.

⁃ Vi kan t.ex. byta ut första elemenetet i listan [1, 2,3] till 5

l = [1, 2, 3]

l[0] = 5

l → [5, 2,3]

(15)

Referenser till värden

(16)

Variabler som referenser till värden

⁃ I de flesta fall är det bättre att se variabler som "etiketter"

som refererar till värden.

⁃ En variabeltilldelning


l1 = [1, 2, 3] 


kan ses som att vi säger "låt etiketten l referera till värdet ..."

⁃ Vi kan låta olika etiketter referara till samma värde:


l2 = l1

(17)

Konsekvenser av att olika variabler kan referera till samma värde

l1 = [1, 2, 3]

# låt l2 referera till samma värde som l1 l2 = l1

# ändra första elementet i värdet som l1 refererar till l1[0] = "hoppsan"

# vad kommer vi få för utskrifter?

print(l1) print(l2)

(18)

Operatorn + på listor returnerar en ny lista, .append() ändrar på existerande lista

frukter_1 = ["apelsin", "banan", "citron"]

frukter_2 = frukter_1 frukter_3 = ["druva"]

# .append() -> lägg till existerande lista frukter_1.append("fikon")

# operatorn + skapar en ny lista från operanderna

# (om de är listor)

frukter_1 = frukter_1 + frukter_3

(19)

Föränderliga värden som skickas som argument till funktioner

def change_and_return_new_list(a_list):

a_list.append("list was changed") return [1, 2, 3]

my_list = ["a", "b", "c"]

# låt also_my_list också referera till värdet som my_list

# refererar till

also_my_list = my_list

# låt my_list referera till det som change_and_return_new_list

# returnerar

my_list = change_and_return_new_list(my_list) print(my_list)

print(also_my_list)

(20)

Ny datatyp: dictionary

nycklar associerade med värden

(21)

Dictionaries

Ett dictionary har element precis som en lista, men istället för index, kommer man åt elementen med via nycklar.

Varje nyckel är associerat med ett värde.

Alla datatyper som är oföränderliga (immutable) kan

användas som nycklar, t.ex. flyttal, heltal, strängar, tupler

Till skillnad från en lista, finns det ingen bestämd ordning på

nyckel-värde-paren i ett dictionary.

(22)

Dictionaries - en mängd nyckel- värde-par

# Ett dictionary omges av {} och består av nycklar och värden:

# { nyckel_1:värde1,

# nyckel_2:värde2,

# ... ,

# nyckel_n:värde_n }

# Exempel

dictionary1 = {"nyckel1":"värde 1", 345:"värde 2", 3:54 }

Ett dictionary används för att lagra värden med associativ åtkomst, dvs att

en nyckel kan användas för att komma åt ett värde. Som en lista, men med

nycklar istället för index. Som nyckel kan alla oföränderliga (immutable)

datatyper användas. Alla datatyper kan vara värden.

(23)

Istället för index använder vi nyckeln

In [1]: dictionary1 = {"nyckel1":"värde 1", 345:"värde 2", 3:54 } In [2]: dictionary1["nyckel1"]

Out[2]: 'värde 1'

In [3]: dictionary1[345]

Out[3]: 'värde 2'

In [4]: dictionary1[3]

Out[4]: 54 In [5]:

Jämfört med en lista så använder vi nyckeln istället för index för att

"komma åt" värdena.

(24)

Vi kan ändra värden genom att använda nyckeln

In [5]: dictionary1 = {"nyckel1":"värde 1", 345:"värde 2", (3):54 } In [6]: dictionary1["nyckel1"]

Out[6]: 'värde 1'

In [7]: dictionary1["nyckel1"] = 1024 In [8]: dictionary1["nyckel1"]

Out[8]: 1024

Precis som att man kan ange ett index vid tilldelning av ett värde på ett element i en lista, så kan man ange en nyckel vid tilldelning av ett

associerat värde i en dictionary.

(25)

Vi kan lägga till element till ett dictionary

In [9]: dictionary1 = {"nyckel1":"värde 1", 345:"värde 2", (3):54 } In [10]: dictionary1["ny nyckel"] = "nytt värde"

In [11]: dictionary1["böcker"] = ["bok 1", "bok 2", "bok 3"]

In [12]: dictionary1["ny nyckel"]

Out[12]: 'nytt värde'

In [13]: dictionary1["böcker"]

Out[13]: ['bok 1', 'bok 2', 'bok 3']

Vi kan lägga till nya värden i ett dictionary genom att använda en ny

nyckel.

(26)

Ny operator: in

⁃ Operatorn in kan användas bl.a. sekvenser (listor och strängar) och dictionaries.

⁃ Returnerar True om den hittar det sökta elementet i sekvensen/bland dictionaryts nycklar.

OBS! Inte samma som det in som används i samband med en for-loop

"a" in "Python är ett programmeringsspråk" → True 4 in [1, 2, 3, 4] → True

4 in [1, 2, 3, [4]] → False

"hej" in { "ja": "yes", "nej": "no", "hej": "hello" } → True

(27)

Loopa igenom ett dictionary

(28)

Alla nycklar/värden/nyckel- värdepar för ett dictionary

⁃ Punktnotation för att komma åt alla

nycklar: dict.keys()

värden: dict.values()

nyckel-värdepar: dict.items()

⁃ " dict " refererar till ett värde av typen dictionary, denna notation används även i pythondokumentationen

⁃ Funktioner som anropas via punktnotation kallas för metoder.

⁃ Metoderna dict.keys() , dict.values() och

dict.items() returnerar en "vy" in i dictionary-värdet.

(29)

Vi kan loopa genom nycklar i ett dictionary

dictionary1 = {"ett": "one", "två": "two", "bil": "car" }

# loopa genom nycklar, explicit (ingen _bestämd_ ordning finns) for key in dictionary1.keys():

print("Key: " + key)

print("Value: " + dictionary1[key])

# loopa genom nycklar, implicit (ingen _bestämd_ ordning finns) for key in dictionary1:

print("Key: " + key)

print("Value: " + dictionary1[key])

Vi kan komma åt alla nycklar antingen implicit eller explicit. Operatorn in kan också användas på nycklarna implicit:

if key_i_am_looking_for in dictionary1

(30)

Vi kan loopa genom värden i ett dictionary

# loopa genom värden, explicit (ingen _bestämd_ ordning finns) for value in dictionary1.values():

print("Value: " + value)

dict.values() , precis som dict.keys() ger en struktur (ett view objekt) som beter sig som en lista (men det är ingen riktig lista). Se

https://docs.python.org/release/3.3.0/library/stdtypes.html#dict-views

för mer information.

(31)

Vi kan loopa genom par av nycklar och värden

# loopa genom par av nycklar och värden explicit for key, value in dictionary1.items():

print("Key: " + key)

print("Value: " + value)

# en lista av tupler med två element per tupel kan loopas igenom på

# samma sätt

list_of_tuples = [("ett", 1), ("två", 2), ("tre", 3)]

for word, number in list_of_tuples:

print("word: " + word)

print("number" + str(number))

dict.items() returnerar en struktur som kan användas som en lista av

tupler med två element per tupel.

(32)

Dataabstraktion

Strukturera information

(33)

Abstraktion

programabstraktion: dela upp problem i delproblem, dela upp en funktion i flera funktioner

dataabstraktion: koppla ihop och strukturera information

(34)

Dataabstraktion

# en variabel per värde pokemon_name = "pidgey"

ability1 = "big-pecks"

ability2 = "tangled-feet"

ability3 = "keen-eye"

Hur gör vi om vi vill ha information om fler eller färre "abilities" på ett

smidigt sätt?

(35)

Dataabstraktion

pokemon_name = "pidgey"

# listor kan användas för att lagra 0 eller fler värden abilities = ["big-pecks", "tangled-feet", "keen-eye"]

Listor kan användas för information som kan fler än ett värde.

Hur gör vi om vi vill ha information om flera pokemons? Ska vi ha

pokemon_name1, pokemon_name2, abilities1, abilities2?

(36)

Dataabstraktion

pokemon1 = ["pidgey", ["big-pecks", "tangled-feet", "keen-eye"]]

pokemon2 = ["ditto", ["imposter", "limber"]]

Vi kan samla ihop informationen om varje pokemon till en lista samt

bestämma den ordning som informationen ska komma i.

(37)

Dataabstraktion

pokemon = [ ["pidgey", ["big-pecks", "tangled-feet", "keen-eye"]], ["ditto", ["imposter", "limber"]] ]

Vi kan sedan samla ihop alla enskilda pokemons till ytterligare en

lista!

(38)

Dataabstraktion

pokemon = [ { "name": "pidgey",

"abilities": ["big-pecks", "tangled-feet", "keen-eye"] }, { "name": "ditto",

"abilities": ["imposter", "limber"] } ]

Vi hade även kunnat använda ett dictionary för att representera en

Pokémon.

(39)

Abstrakta datatyper (ADT)

⁃ Barbara Liskov, Stephen Zilles. 1974. "Programming with abstract data types"

⁃ Abstrakt datatyp

datastruktur

funktioner som används på dessa datastrukturer

⁃ Föregångare till en objektorienterad approach.

(40)

Exempel på abstrakt datatyp

⁃ Kö

lista med element är kön, index 0 är nästa på tur

funktionen create_empty_queue() som returnerar en tom kö

funktionen enqueue(value, queue) som lägger till värdet

value till slutet på kön queue

funktionen dequeue(queue) som returnerar nästa värde i

kön och plockar även bort det från kön

(41)

Bearbetning av nästlade

datastrukturer

(42)

Nästlade datastrukturer

⁃ Ett värde är en nästlad datastruktur om

värdet innehåller flera värden och

minst av värdena i sin tur innehåller flera värden

⁃ Exempel:

[["Ada Lovelace", 1815], ["Joan Clarke", 1917]]

[ { "name": "Ada Lovelace", "birthyear": 1815 }, { "name": "Joan Clarke", "birthyear": 1815 } ]

{ "name": "ditto", "abilities": ["imposter", "limber"] }

(43)

Hur kommer vi åt nästlade värden?

lista1 = [["a", "b", "c"], ["d", "e", "f"]]

# första elementet i lista1 lista1[0]

# första elementet i första elementet i lista1 lista1[0][0]

# andra elementet i första elementet i lista1 lista1[0][1]

(44)

Hur kommer vi åt nästlade värden?

dict1 = { "frukter": ["a", "b", "c"], "bilar": ["d", "e", "f"] }

# värdet associerat med nyckeln "frukter"

dict1["frukter"]

# första elementet i listan associerad med nyckeln "frukter"

dict1["frukter"][0]

# andra elementet i listan associerad med nyckeln "frukter"

dict1["frukter"][1]

(45)

Exempel på bearbetning av nästlad datastruktur

Listor i listor

(46)

En nästlad loop för att bearbeta en nästlad datastruktur

yttre_lista = [ ["a", "b", "c"], ["d", "e", "f", "g"] ]

# skriv ut varje element i listan yttre_lista index1 = 0

while index1 < len(yttre_lista):

print(yttre_lista[index1]) index1 += 1

# om vi för varje inre lista i yttre_lista vill skriva ut den

# inre listans element?

index1 = 0

while index1 < len(yttre_lista):

inre_lista = yttre_lista[index1]

# kod som skriver ut varje element i inre_lista

(47)

En nästlad loop för att bearbeta en nästlad datastruktur

yttre_lista = [ ["a", "b", "c"], ["d", "e", "f", "g"] ]

# skriv ut varje element i listan yttre_lista index1 = 0

while index1 < len(yttre_lista):

print(yttre_lista[index1]) index1 += 1

# om vi för varje inre lista i yttre_lista vill skriva ut den

# inre listans element?

index1 = 0

while index1 < len(yttre_lista):

inre_lista = yttre_lista[index1]

# kod som skriver ut varje element i inre_lista index2 = 0

while index2 < len(inre_lista):

print(inre_lista[index2]) index2 += 1

index1 += 1

(48)

En nästlad loop för att bearbeta en nästlad datastruktur

yttre_lista = [ ["a", "b", "c"], ["d", "e", "f", "g"] ]

# skriv ut varje element i listan yttre_lista for yttre_element in yttre_lista:

print(yttre_element)

# om vi för varje inre lista i yttre_lista vill skriva ut den

# inre listans element?

for yttre_element in yttre_lista:

for inre_element in yttre_element:

print(inre_element)

(49)

Exempel på bearbetning av nästlad datastruktur

Dictionaries i listor

(50)

Enklare formattering av strängar

⁃ Metoden sträng.format(arg1, ... argN)

⁃ Ersätter förekomster av "{}" med motsvarande argument

"Hej {} och {}!".format("Ada", "Charles") → "Hej Ada och Charles!"

⁃ Referera till specifikt argument med index: "{0}" refererar till första, "{1}" refererar till andra osv

"Hej {1} och {0}!".format("Ada", "Charles") → "Hej Charles och Ada!"

⁃ Argumenten till .format() kan även vara variabler.

(51)

Enklare formattering av strängar

⁃ Python 3.6 och uppåt har även stöd för sträng-litteraler, eller "f-strängar".

⁃ Exempel om namn1 = "Ada" och namn2 = "Charles"

f"Hej {namn1} och {namn2}" → "Hej Ada och Charles"

(52)

Bearbeta lista av dictionaries 1

pokemons = [ { "name": "bulbasaur", "abilities": ["chlorophyll", "overgrow"] }, { "name": "squirtle", "abilities": ["rain-dish", "torrent"] } ]

books = [ { "title": "Introduction to Python", "pages": 314 },

{ "title": "Another introduction to Python", "pages": 413 } ] def print_dictionaries(list_of_dictionaries):

# gå igenom listan av dictionaries

for dictionary in list_of_dictionaries:

# gå igenom alla nycklar i aktuellt dictionary for key in dictionary:

print(f"Key {key} has value: {dictionary[key]}") print("pokemons:")

print_dictionaries(pokemons) print("\nbooks:")

print_dictionaries(books)

(53)

Exempel på bearbetning av nästlad datastruktur

Lista med blandade datatyper

(54)

Göra olika saker beroende på datatyp

⁃ Använd funktionen type() för att ta reda på datatyp

type(5) → int

type("hejsan") → str

type(["hoppsan"]) → list

type({ "storlek": 5000 }) → dict

(55)

En nästlad loop för att bearbeta en lista med både värden som är listor och värden som inte är listor

blandad_lista = [ "a", ["b", "c"], "d", "e", ["f", "g"] ] for element in blandad_lista:

if type(element) == list:

for inre_element in element:

print(inre_element) else:

print(element)

(56)

Leta efter värde i nästlad lista

blandad_lista = [ "a", ["b", "c"], "d", "e", ["f", "g"] ] def look_for_value(needle, haystack):

for value in haystack:

if type(value) == list:

for inner_value in value:

if inner_value == needle:

return True elif value == needle:

return True return False

(57)

Exempel på bearbetning av nästlad datastruktur

Listor med dictionaries som i sin tur kan

innehålla listor

(58)

Bearbeta lista av dictionaries 2

pokemons = [ { "name": "bulbasaur", "abilities": ["chlorophyll", "overgrow"] }, { "name": "squirtle", "abilities": ["rain-dish", "torrent"] } ]

books = [ { "title": "Introduction to Python", "pages": 314 },

{ "title": "Another introduction to Python", "pages": 413 } ]

(59)

Bearbeta lista av dictionaries 2

pokemons = [ { "name": "bulbasaur", "abilities": ["chlorophyll", "overgrow"] }, { "name": "squirtle", "abilities": ["rain-dish", "torrent"] } ] books = [ { "title": "Introduction to Python", "pages": 314 },

{ "title": "Another introduction to Python", "pages": 413 } ] def print_dictionaries(list_of_dictionaries):

# gå igenom listan med dictionaries

for dictionary in list_of_dictionaries:

# gå igenom alla nycklar i varje dictionary for key in dictionary:

# i de fall som värdet för en nyckel är en lista if type(dictionary[key]) == list:

print("Value of key {} is a list:".format(key))

# gå igenom varje värde i listan som finns i dictionaryt for value in dictionary[key]:

print("- {}".format(value))

# när värdet i dictionaryt inte är en lista else:

print("Key {} has value: {}".format(key, dictionary[key])) print("pokemons:")

print_dictionaries(pokemons) print("\nbooks:")

print_dictionaries(books)

(60)

Problem med enbart loopar och nästlade strukturer

⁃ Vi behöver en loop per nivå.

⁃ Vad gör vi för att bearbeta en struktur med godtyckligt djup?

⁃ ... använd rekursion.

(61)

Rekursion

(62)

Rekursiva funktioner

⁃ En funktion är rekursiv om den anropar på sig själv direkt

eller indirekt.

(63)

Rekursion

⁃ När en funktion anropar sig själv

⁃ Vad tror ni händer nedan?

def skriv_ut_hej(heltal):

print(f"Hej {heltal}") skriv_ut_hej(heltal + 1) print("Klar!")

skriv_ut_hej(0)

(64)

Rekursion - villkor behövs för att får ett slut

def skriv_ut_hej(heltal):

if heltal == 10:

print("Klar!") else:

print(f"Hej {heltal}") skriv_ut_hej(heltal + 1) skriv_ut_hej(0)

(65)

Rekursiv problemlösning

⁃ För att lösa ett problem rekursivt, behöver vi formulera eller dela upp det på ett sådant sätt så att delarna är mindre varianter av det större problemet.

⁃ Om vi har problemet summera talen

1

,

2

,

75

,

2

och

7

. Att uttrycka det som

1 + 2 + 75 + 2 + 7

är att försöka lösa allt på en gång.

⁃ Ett alternativt sätt är uttrycka det som

1

+ summan av de resterande talen;

2

,

75

,

2

,

7

⁃ Summan av de resterande talen i sin tur kan vi uttrycka på samma sätt,

2

+ summan av de resterande talen;

75

,

2

,

7

⁃ Vi har hittat ett sätt att formulera problemet så att vi kan

tillämpa samma lösning på mindre och mindre varianter av

samma problem.

(66)

Ett första försök

numbers = [1, 2, 75, 6, 7]

def sum_list_rec(values):

return values[0] + sum_list_rec(values[1:]) result = sum_list_rec(numbers)

print(result)

(67)

Ett första försök

numbers = [1, 2, 75, 6, 7]

def sum_list_rec(values):

return values[0] + sum_list_rec(values[1:]) result = sum_list_rec(numbers)

print(result)

# Vad är summan av alla tal i en tom lista?

(68)

Summera alla tal i en lista

numbers = [1, 2, 75, 6, 7]

def sum_list_rec(values):

# summan av värdena i en tom lista är 0 if not values:

return 0

# summan av värdena i en icke-tom lista är första värdet + summan av # resten av värdena i listan

return values[0] + sum_list_rec(values[1:]) result = sum_list_rec(numbers)

print(result)

(69)

Nytt problem: summan av alla tal från n till 0?

⁃ Summan av alla tal från n till 0 är n + summan av n-1 till 0.

(70)

Försök 1: Summan av alla tal från n till 0

def sum_rec(n):

return n + sum_rec(n-1)

(71)

Försök 1: Summan av alla tal från n till 0

def sum_rec(n):

return n + sum_rec(n-1)

# Vi behöver identifiera när vi ska sluta...

(72)

Summan av alla tal från n till 0

def sum_rec(n):

if n == 0:

return 0

return n + sum_rec(n-1)

(73)

Mönster för att skriva en rekursiv funktion

⁃ Vi letar efter det "enklaste" fallet av problemet som ska lösas, basfallet.

⁃ Basfallet är det problemfall som är så enkelt att svaret är givet.

⁃ Basfallet följs sedan av ett eller flera rekursiva anrop på en

"enklare" variant av ursprungsproblemet.

⁃ Se till att alla return -satser returnera värde av samma

datatyp.

(74)

Leta efter ett värde i en lista

numbers = [1, 2, 75, 6, 7, 75, 6, 7, 75, 6, 7]

def look_for_value_rec(value, values):

# Inget värde kan finnas i en tom lista if not values:

return False

# om första värdet är det värde vi letar efter kan vi sluta leta elif values[0] == value:

return True

# om inte första värdet var det vi letade efter returnera # resultatet av att leta efter värdet i resten av listan else:

return look_for_value_rec(value, values[1:])

print("Sökning efter 314: {}".format(look_for_value_rec(314, numbers))) print("Sökning efter 7: {}".format(look_for_value_rec(7, numbers)))

(75)

Spara bara strängar

mixed_list = ["ett", 2, "sjuttiofem", 6, 7, 75, 6, "sju"]

def keep_strings_rec(values):

# om listan är tom så resultatet en tom lista if not values:

return []

# om första värdet i listan är en sträng så är resultatet

# en lista med den strängen + alla strängar i resten av values elif type(values[0]) == str:

return [values[0]] + keep_strings_rec(values[1:])

# om första värdet i listan inte var en sträng så är resultatet # alla strängar i resten av listan

else:

return keep_strings_rec(values[1:]) print(keep_strings_rec(mixed_list))

(76)

Spara bara strängar

def keep_strings_rec(values):

if not values:

return []

elif type(values[0]) == str:

return [values[0]] + keep_strings_rec(values[1:]) else:

return keep_strings_rec(values[1:])

(77)

Varning för globala variabler

(78)

Den andra funktionen ger 0 poäng på tentan...

def keep_strings_good(values):

if not values:

return []

elif type(values[0]) == str:

return [values[0]] + keep_strings_good(values[1:]) else:

return keep_strings_good(values[1:])

answer = []

def keep_strings_bad(values):

if len(values) > 0:

if type(values[0]) == str:

answer.append(values[0]) keep_strings_bad(values[1:]) return answer

# men det funkar ju eller?

print(keep_strings_good(["ett", 2, "sjuttiofem", 6, 7])) print(keep_strings_bad(["ett", 2, "sjuttiofem", 6, 7]))

(79)

Den andra funktionen ger 0 poäng på tentan...

def keep_strings_good(values):

if not values:

return []

elif type(values[0]) == str:

return [values[0]] + keep_strings_good(values[1:]) else:

return keep_strings_good(values[1:])

answer = []

def keep_strings_bad(values):

if len(values) > 0:

if type(values[0]) == str:

answer.append(values[0]) keep_strings_bad(values[1:]) return answer

# kan vi använda funktionerna flera gånger?

print("Två anrop till keep_strings_good()")

print(keep_strings_good(["ett", 2, "sjuttiofem", 6, 7])) print(keep_strings_good(["ett", 2, "sjuttiofem", 6, 7]))

print("\nTvå anrop till keep_strings_bad()")

print(keep_strings_bad(["ett", 2, "sjuttiofem", 6, 7])) print(keep_strings_bad(["ett", 2, "sjuttiofem", 6, 7]))

(80)

Räcker det med att flytta in answer in i funktionen?

def keep_strings_bad(values):

answer = []

if len(values) > 0:

if type(values[0]) == str:

answer.append(values[0]) keep_strings_bad(values[1:]) return answer

print(keep_strings_bad(["ett", 2, "sjuttiofem", 6, 7]))

(81)

Trädrekursion

(82)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1 2 3

(83)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1 2 3

(84)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

⁃ Summan är värdet på detta löv + summan av övriga värden.

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1 2 3

(85)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

⁃ Summan är värdet på detta löv + summan av övriga värden.

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1 2 3

(86)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

⁃ Summan är värdet på detta löv + summan av övriga värden.

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1 2 3

(87)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

⁃ Summan av inga värden är 0 .

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1 2 3

(88)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

⁃ Summan är värdet på detta löv + summan av övriga värden.

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1 2 3

(89)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

⁃ Summan är värdet på detta löv + summan av övriga värden.

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1 2 3

(90)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

⁃ Summan är värdet på detta löv + summan av övriga värden.

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1 2

5

3

(91)

Platt lista som trädstruktur

⁃ [ 1, 2, 3]

Problem: Vad är summan av alla löv?

⁃ Alla noder är löv, dvs alla noder har värden.

⁃ Summan är värdet på detta löv + summan av övriga värden.

def sum_rec(values):

if not values:

return 0 else:

return values[0] + sum_rec(values[1:)

[ ]

1

6

2 3

(92)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde → summan av delträdet.

⁃ Summan av ett (del)träd är värdet på denna nod + summan av övriga noder.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2 3

(93)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde -> summan av delträdet.

⁃ Summan är värdet på detta löv + summan av övriga värden.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2 3

(94)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde, dvs, summan av delträdet.

⁃ Summan är värdet på detta löv + summan av övriga värden.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2 3

(95)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde, dvs, summan av delträdet.

⁃ Summan är värdet på detta löv + summan av övriga värden.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2

5

3

(96)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde, dvs, summan av delträdet.

⁃ Summan är värdet på detta löv + summan av övriga värden.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2

5

3

(97)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde, dvs, summan av delträdet.

⁃ Summan är värdet på detta löv + summan av övriga värden.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2

5

3

(98)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde, dvs, summan av delträdet.

⁃ Summan är värdet på detta löv + summan av övriga värden.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2

5

3

9

(99)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde, dvs, summan av delträdet.

⁃ Summan är värdet på detta löv + summan av övriga värden.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2

5

3

15

(100)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde, dvs, summan av delträdet.

⁃ Summan är värdet på detta löv + summan av övriga värden.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2 3

20

(101)

Nästlade strukturer kan ses som trädstrukturer

⁃ [1, [2, 3], [ [4, 5], 6 ] ]

Problem: Vad är summan av alla löv?

⁃ Om nod inte är ett löv, räkna ut dess värde, dvs, summan av delträdet.

⁃ Summan är värdet på detta löv + summan av övriga värden.

[ ]

[ ] 6

4 5

1 [ ] [ ]

2 3

21

(102)

Summera alla värden i en nästlad lista

def sum_of_all_values(values):

# om vi inte har några värden är summan 0 if not values:

return 0

# om noden inte är ett värde, räkna ut delträdets värde och addera det till # resten av värdena

elif type(values[0]) == list:

return sum_of_all_values(values[0]) + sum_of_all_values(values[1:]) # noden är ett löv, addera dess värde till resten av värdena i trädet else:

return values[0] + sum_of_all_values(values[1:])

# sum_of_all_values([1, [2, 3], [[4, 5], 6]])

# sum_of_all_values([1, [2, 3], [[4, 5, [6, 7, [8]]], 9]])

(103)

Leta efter ett värde i en nästlad lista

numbers1 = [[1, 2, 75, 6, 7], [75, 6, 7], [75, 6, 7], [1, 2, 75, 6, 7], [75, 6, 7], [73]]

numbers2 = [[1, 2], 75, 6, 7, [75, 6, 7], 75, 6, 7, [1, 2, 75, 6, 7], 75, 6, 7, 73]

numbers3 = [[1, 2], [75, [6, 7]], [75, [6, 7]], [75, [6, 7]], [1], 2, [75, [6, [7, [75], 6], 7]], 73]

def look_for_value_rec_all(value, values):

# Inget värde kan finnas i en tom lista if not values:

return False

# om första värdet är en lista, returnera resultatet av att # leta i både den listan och resten av values

elif type(values[0]) == list:

return (look_for_value_rec_all(value, values[0]) or look_for_value_rec_all(value, values[1:]))

# om första värdet inte är en lista, kolla om det är det värde # vi letar efter, returnera i så fall True

elif values[0] == value:

return True

# om inte första värdet varken var en lista eller det vi letade efter # returnera resultatet av att leta efter värdet i resten av listan else:

return look_for_value_rec_all(value, values[1:])

(104)

Spara bara strängar i en nästlad lista

mixed_list = ["ett", [2, "sjuttiofem", 6], 7, [[75], [6, ["sju"]]]]

def keep_strings_rec_all(values):

# om listan är tom så resultatet en tom lista if not values:

return []

# om första värdet är en lista är resultatet en lista med listan # utan några andra datatyper än strängar + bearbetningen av resten # av listan

elif type(values[0]) == list:

return ([keep_strings_rec_all(values[0])] + keep_strings_rec_all(values[1:]))

# om första värdet i listan är en sträng så är resultatet

# en lista med den strängen + alla strängar i resten av values elif type(values[0]) == str:

return [values[0]] + keep_strings_rec_all(values[1:])

# om första värdet i listan inte var en sträng så är resultatet # alla strängar i resten av listan

else:

return keep_strings_rec_all(values[1:]) print(keep_strings_rec_all(mixed_list))

(105)

Överkurs-exempel

(106)

Rekursiva funktioner kan "utforska"

flera olika lösningsvägar med trädrekursion

Exempel: En karta med enkelriktade vägar representeras som en graf.

Problem: Givet en startpunkt A kan vi ta oss till platsen B?

Returnera vägen.

Representation: Vi representerar grafen som ett dictionary där nycklarna är noder vars värde är en lista med de noder vi kan nå.

e a f

g

h

i

b c

d

(107)

Hitta vägen

map1 = {"a": ["b", "c"], "b": [],

"c": ["d"], "d": ["a"], "e": ["b"]}

def get_path(s_node, e_node, a_map, visited):

# är e_node direkt tillgänglig?

if e_node in a_map[s_node]:

return visited + [s_node, e_node]

# kolla om vi kan ta oss till e_node från någon av grannarna till s_node return get_path_hlp(a_map[s_node], e_node, a_map, visited + [s_node])

def get_path_hlp(s_nodes, e_node, a_map, visited):

# om s_nodes är tom så kan vi inte ta oss till e_node if not s_nodes:

return []

# om vi inte redan besökt s_nodes[0]

elif s_nodes[0] not in visited:

# kolla om vi kan ta oss till e_node därifrån eller någon av de övriga # nodern i s_nodes

path = get_path(s_nodes[0], e_node, a_map, visited) if path:

return path else:

return get_path_hlp(s_nodes[1:], e_node, a_map, visited) # om vi redan besökt s_nodes[0]

else:

# kolla om vi kan ta oss till e_node från någon av de övriga noderna # i s_nodes

return get_path_hlp(s_nodes[2:], e_node, a_map, visited)

a d

e b

c

(108)

Hitta vägen

map1 = {"a": ["b", "c"], "b": [],

"c": ["d"], "d": ["a"], "e": ["b"]}

def get_path(s_node, e_node, a_map, visited):

if e_node in a_map[s_node]:

return visited + [s_node, e_node]

return get_path_hlp(a_map[s_node], e_node, a_map, visited + [s_node])

def get_path_hlp(s_nodes, e_node, a_map, visited):

if not s_nodes:

return []

elif s_nodes[0] not in visited:

path = get_path(s_nodes[0], e_node, a_map, visited) if path:

return path else:

return get_path_hlp(s_nodes[1:], e_node, a_map, visited) else:

return get_path_hlp(s_nodes[2:], e_node, a_map, visited)

a d

e b

c

(109)

Hitta vägen (med for-loop)

map1 = {"a": ["b", "c"], "b": [],

"c": ["d"], "d": ["a"], "e": ["b"]}

def get_path(s_node, e_node, a_map, visited):

# är e_node direkt tillgänglig?

if e_node in a_map[s_node]:

return visited + [s_node, e_node]

# kolla om vi kan ta oss till e_node från någon av grannarna till s_node for next_node in a_map[s_node]:

if next_node not in visited:

path = get_path(next_node, e_node, a_map, visited + [s_node]) if path:

return path

# om vi kommer hit kunde vi inte hitta någon väg return []

a d

e b

c

(110)

Större karta

map2 = {"a": ["d"],

"b": ["e", "g"], "c": ["e", "h"], "d": ["g"],

"e": ["d"],

"f": ["g", "h"], "g": [],

"h": ["e", "i"],

"i": ["f"]} a

e f

g

h

i

b c

d

References

Related documents

Ett mål för framtiden är att data med ursprung i (anonymiserade) personuppgifter ska inkluderas. Regeringen hoppas också att stora data och öppna data kommer

Based on known input values, a linear regression model provides the expected value of the outcome variable based on the values of the input variables, but some uncertainty may

Punkt Utbredningen är knuten till en eller flera punkter på en eller flera referenslänkar (används t.ex. för företeelsetyperna; Höjdhinder upp till 4,5 meter, Väghinder,

• Data från BIS ligger till grund för besiktningsprotokollen då Bessy hämtar data från BIS.. Varför viktigt med

‒ Automatgenererat mail till projektledaren 6 månader före angivet ibruktagningsdatum i Patcy för kontroll att ibruktagningsdatum i Patcy stämmer med projektets gällande tidplan.

In particular, the purpose of the research was to seek how case companies define data- drivenness, the main elements characterizing it, opportunities and challenges, their

2) The recommended servo drive is defined for the stall current of the motor; if more than double the stall torque is required during the acceleration phase, the next larger

Det finns lösningar på marknaden i olika former för detta redan men frågan är att se vilket databassystem av PostgreSQL och MongoDB som kan tänkas prestera bättre när det