Göm meny

Filer och kontexthanterare

Skriv lösningarna till uppgifterna i en och samma fil och testa koden själv innan du använder rättningsskriptet. Att kunna testa sin kod är en viktig del av att programmera!

Att lära dig från uppgifterna

  • Förstå hur filer öppnas och stängs för läsning och skrivning.
  • Förstå hur kontexthanterare fungerar för filhantering

Man kan få max 95 poäng och för att få godkänt krävs 65 poäng (85 för väl godkänt). Försök dock att lösa alla uppgifter då inte alla fel upptäcks av rättningsskriptet. Om ni har lite marginal kan ni kanske bli godkända även om assistenten som rättar hittar något sådant fel.

Förberedelser

Två datafiler behövs för att lösa många av uppgifterna nedan. Börja därför med att kopiera dem från kurskatalogen. Du hittar filerna firstnames och lastnames i katalogen /courses/729G46/kursmaterial/tema2.

Filen firstnames innehåller förnamn och filen lastnames innehåller efternamn.

Filer att hämta via webben istället för via kurskatalogen:

Högerklicka på länkarna och välj “Spara som…”.

Uppgift 8.1

8.1.1 (5p)

Skriv en funktion print_lines(path) som tar sökvägen till en fil representerat som en sträng som argument. Funktionen skall skriva ut alla rader i filen.

Exempel

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
>>> print_lines('data/firstnames')
Marie
Ida
Maria
Sofia
Rosalind
Cecilia
Jocelyn
Dorothy
Ada
Barbara
Grace

Tips 1: Innan vi kan läsa från en fil, så måste vi öppna filen för läsning med hjälp av funktionen open(). Ett filobjekt måste stängas när man är färdig med det.

Tips 2: När vi har öppnat en fil så läser vi den med hjälp av metoden readlines(). Du kan läsa pythondokumentationen för readlines() översiktligt. Du behöver inte förstå allt, men du får exempel på den terminologi som används. Vissa termer kommer kanske att vara nya. Vad betyder t.ex. EOF?

8.1.2 (5p)

Skriv en funktion save_strings(path, lst) som tar en sökväg och en lista av strängar och skriver strängarna till filen, en sträng per rad. Om filen redan existerar ska innehållet skrivas över. Använd file.write för att skriva varje sträng i lst till filen.

Tips: Kom ihåg att tecknet för en radbrytning är '\n'.

Exempel

1
2
>>> save_strings('stringfile.txt', ['rad 1', 'rad 2', 'rad 3'])
>>> save_strings('stringfile.txt', ['rad 4', 'rad 5', 'rad 6'])

Innehållet i stringfile.txt efter båda anropen ovan:

rad 4
rad 5
rad 6

8.1.3 (5p)

Skriv en funktion save_more_strings(path, lst) som tar en sökväg och en lista av strängar och skriver strängarna till filen, en sträng per rad. Om filen redan existerar ska innehållet läggas till i slutet av filen. Använd file.writelines för att skriva hela listan till filen i ett anrop.

Exempel

1
2
>>> save_strings('stringfile.txt', ['rad 1', 'rad 2', 'rad 3'])
>>> save_more_strings('stringfile.txt', ['rad 4', 'rad 5', 'rad 6'])

Innehållet i stringfile.txt efter båda anropen ovan:

rad 1
rad 2
rad 3
rad 4
rad 5
rad 6

Förberedelser

Två datafiler behövs för att lösa många av uppgifterna nedan. Börja därför med att kopiera dem från kurskatalogen. Du hittar filerna firstnames och lastnames i katalogen /courses/729G46/kursmaterial/tema2.

Filen firstnames innehåller förnamn och filen lastnames innehåller efternamn.

Filer att hämta via webben istället för via kurskatalogen:

Högerklicka på länkarna och välj “Spara som…”.

Uppgift 8.2 (5p)

Skriv en funktion count_lines(path) som returnerar antalet rader i en fil.

Använd kontexthanteraren för filobjekt med hjälp av with för att slippa att manuellt stänga filen.

Exempel

1
2
>>> count_lines('data/firstnames')
11

Uppgift 8.3 (5p)

Skriv funktionen get_names_starting_with(path, letter) som läser in en fil med namn och returnerar en lista på alla namn som börjar på bokstaven letter. Det ska inte spela någon roll ifall letter är gemen eller versal.

Tips: För att slippa anropa str.strip eller str.rstrip på varje element för att bli av med radbrytningstecknen kan man istället för att läsa in raderna med file.readlines använda file.read, som returnerar hela filen som en sträng, och sedan strängmetoden str.splitlines (eller str.split('\n')), för att dela upp den strängen i rader. Sätter man ihop det blir det t.ex. f.read().splitlines().

Exempel

1
2
3
4
>>> get_names_starting_with('data/lastnames', 'C')
['Curie', 'Crowfoot Hodgkin']
>>> get_names_starting_with('data/firstnames', 'm')
['Marie', 'Maria']

Uppgift 8.4 (10p)

Skriv funktionen find_in_file(path, search_str) som tar en sökväg och en söksträng. Filen skall returnera en tupel med två element, radnumret (numrerat från 1) på den första raden som innehåller search_str samt en sträng som representerar hela raden (utom radbrytningen). Om ingen rad i filen innehåller search_str skall funktionen returnera None.

Exempel

1
>>> find_in_file('data/lastnames', 'Love')

Uppgift 8.5 (5p)

Skriv funktionen find_all_in_file(path, search_str) som tar en sökväg och en söksträng. Filen skall returnera en lista av tupler med två element*. Varje tupel skall innehålla radnumret (numrerat från 1) på den rad som innehåller search_str samt en sträng som representerar hela raden (utom radbrytningen). Om ingen rad i filen innehåller search_str skall funktionen returnera en tom lista.

* Detta är ett exempel på en så kallad nästlad datastruktur. Vi kommer titta mer på dessa längre fram i kursen.

Exempel

1
2
3
4
5
6
>>> find_all_in_file('data/lastnames', 'Love')
[(9, 'Lovelace')]
>>> find_all_in_file('data/lastnames', 'el')
[(7, 'Bell Burnell'), (9, 'Lovelace')]
>>> find_all_in_file('data/lastnames', '-')
[(3, 'Goeppert-Mayer'), (6, 'Payne-Gaposchkin')]

Uppgift 8.6 (10p)

Skriv en funktion get_random_name(firstnames_path, lastnames_path) som skapar slumpmässiga namn genom att använda för- och efternamn från de angivna filerna. För- och efternamn får inte komma från samma rad i båda filerna, dvs. det slumpade namnet skall inte vara ett av de riktiga namnen.

Tips: För att garanterat välja två olika slumpmässiga tal kan man använda random.sample(range(lowest, highest+1), k=2).

Uppgift 8.7 (10p)

Skriv funktionen combine_lines(input_path1, input_path2, sep) som tar två sökvägar och en separator sep som argument. Funktionen skall läsa de båda filerna (som alltså måste existera) och returnera en lista med strängar som skapats genom att slå ihop rad 1 (exklusive radbrytningar) från båda filerna med sep mellan dem, rad 2 från båda filerna med sep mellan, osv.

Exempel

1
2
3
4
>>> combine_lines('data/firstnames', 'data/lastnames', ' ')
['Marie Curie', 'Ida Noddack', 'Maria Goeppert-Mayer', 'Sofia Vasiljevna Kovalevskaja', 'Rosalind Franklin', 'Cecilia Payne-Gaposchkin', 'Jocelyn Bell Burnell', 'Dorothy Crowfoot Hodgkin', 'Ada Lovelace', 'Barbara McClintock', 'Grace Hopper']
>>> combine_lines('data/lastnames', 'data/firstnames', ' är efternamnet och förnamnet är ')
['Curie är efternamnet och förnamnet är Marie', 'Noddack är efternamnet och förnamnet är Ida', 'Goeppert-Mayer är efternamnet och förnamnet är Maria', 'Vasiljevna Kovalevskaja är efternamnet och förnamnet är Sofia', 'Franklin är efternamnet och förnamnet är Rosalind', 'Payne-Gaposchkin är efternamnet och förnamnet är Cecilia', 'Bell Burnell är efternamnet och förnamnet är Jocelyn', 'Crowfoot Hodgkin är efternamnet och förnamnet är Dorothy', 'Lovelace är efternamnet och förnamnet är Ada', 'McClintock är efternamnet och förnamnet är Barbara', 'Hopper är efternamnet och förnamnet är Grace']

Uppgift 8.8 (5p)

Skriv funktionen combine_and_save_names(firstnames_path, lastnames_path, output_path) som tar tre sökvägar som argument. Funktionen skall läsa de båda första filerna (som förväntas innehålla förnamn respektive efternamn på personer) och skapa en lista med strängar genom att slå ihop rad 1 (exklusive radbrytningar) från båda filerna, rad 2 från båda filerna, osv. enligt mönstret nedan. Dessa strängar skall sedan skrivas till filen output_path. Om filen output_path redan existerar skall dess innehåll skrivas över.

Använd funktioner från uppgifterna ovan för att lösa problemet, det är inte tillåtet att anropa open direkt från combine_and_save_names.

Exempel

1
>>> combine_and_save_names('data/firstnames', 'data/lastnames', 'scientists.csv')

Innehåll i scientists.csv efter att ha kört raden ovan:

Marie,Curie
Ida,Noddack
Maria,Goeppert-Mayer
Sofia,Vasiljevna Kovalevskaja
Rosalind,Franklin
Cecilia,Payne-Gaposchkin
Jocelyn,Bell Burnell
Dorothy,Crowfoot Hodgkin
Ada,Lovelace
Barbara,McClintock
Grace,Hopper

Uppgift 8.9 (10p)

Skriv funktionen get_first_name(path, lastname) som tar in ett efternamn och en sökväg som argument. Sökvägen ska gå till en fil som matchar formatet i scientists.csv, dvs en CSV-fil med förnamn i första kolumnen och efternamn i andra kolumnen. Funktionen ska returnera det första förnamnet på den första personen med det angivna efternamnet i den angivna filen. Använd scientists.csv som exempel.

Tips: Strängmetoden str.split är användbar för att separera för- och efternamn. Kom ihåg att efternamn kan ha mellanslag!

Uppgift 8.10 (5p)

Skriv en funktion get_names_of_length(path, length) som returnerar en lista av alla namn av längden length i en fil med sökvägen path.

Uppgift 8.11 (5p)

Skriv en funktion get_longest_name(path) som plockar fram det längsta namnet i den angivna filen.

Uppgift 8.12 (10p)

Skriv en funktion get_palindromes(path) som returnerar en lista med alla namn som är palindrom från en given fil. Det räcker att ett namn är ett palindrom när alla bokstäver konverterats till gemener. (Ett palindrom är en sekvens tecken som blir samma oavsett om den läses framifrån eller bakifrån, t.ex. “kajak”, “apa” eller “tillit”.)

Exempel

1
2
>>> get_palindromes('data/firstnames')
['Ada']

Sidansvarig: Johan Falkenjack
Senast uppdaterad: 2025-08-05