Programmering grundkurs Föreläsning 12 Jody Foo, jody.foo@liu.se
Föreläsningsöversikt Tentan Laboration 7 Skriva till fil Hantering av flaggor m.m. till egna skript med argparse Lite repetition syntax - beståndsdelar hos ett program hur uttryck beräknas OOP
Datorsalstentan logistik på plats, upplägg, inlämning
Datorsalstenta Anmälan som vanligt via Lisam två tillfällen med olika tentor. Kl 8.00-12.00 samt kl. 14.00-18.00 Info på kurshemsidan under "Datorsalstenta" Allmän info https://www.ida.liu.se/~examadm/rutiner/student/index.sv.shtml
Sal, inloggning, kontroller Information om sal vid SU17 Inloggning Steg 1: Välj "Exam System" i sessionsmenyn Steg 2: Logga in med LiU-ID och ditt vanliga lösenord Steg 3: Följs instruktioner på skärmen, engångslösenord fås vid ID-kontroll Kontroll av bok
Frågor under tentan Praktiska frågor: jour-assistenter Frågor om tentauppgifter: använd studentklienten Studentklienten: program som startas automatiskt vid inloggning och används för kommunikation med examinator samt inlämning av uppgifter
Filer Din hemkatalog under tentan nås via ~/ och /home/student_tilde Tentan som PDF samt eventuella filer som hör ihop med tentan finns i katalogen ~/given_files ~/given_files är skrivskyddad Spara din kod direkt i din hemkatalog, t.ex. ~/uppg11.py
Tentaupplägg Två delar, Del 1 och Del 2 Del 1: grundläggande uppgifter, samma omfattning Del 2: något mer omfattande uppgifter Inga avdrag för avvikelser från PEP8 eller PEP257
Del 1 Del 1 innehåller fem uppgifter: 1.1, 1.2, 1.3, 1.4, 1.5 Varje uppgift i Del 1 innehåller tre deluppgifter, t.ex. 1.1.1, 1.1.2, 1.1.3 På varje deluppgift kan man få 0; 0,5 eller 1 poäng För att få godkänt på en uppgift krävs 2 av max 3 poäng. För att gå godkänt på Del 1 måste alla uppgifter vara godkända.
Del 2 Rättas ej om Del 1 inte är godkänd (lösningsförslag kommer skickas ut efter tentan) Inga deluppgifter 0; 0,5 eller 1 poäng per uppgift Uppgift 2.1 och 2.2 är av samma svårighetsgrad Uppgift 2.3 och 2.4 är av samma svårighetsgrad och svårare än 2.1 och 2.2
Betyg Betyg 3: Godkänd på del 1 + 1 poäng på del 2. Betyg 4: Godkänd på del 1 + 2 poäng på del 2. Betyg 5: Godkänd på del 1 + 3 poäng på del 2.
Inlämning av uppgifter En fil per uppgift, inklusive deluppgifter. T.ex. lämnas svar på deluppgifterna 1.1.1, 1.1.2 och 1.1.3 i samma fil Döp filen så att uppgiftsnummret finns med, t.ex. uppg11.py för ovanstående deluppgifter. Filen skickas in via studentklienten: 1. Tryck på knappen "Skicka in uppgift" 2. Välj vilken uppgift och välj vilken fil som skickas in 3. Bekräftelse på att filen är mottagen "Begäran mottagen"
Laboration 7: Rättstavning Fortsättning på laboration 2 Skript som använder ordfrekvensdata för att hitta okända ord i en text och föreslå alternativ till dessa ord med hjälp av redigeringsavstånd T.ex. hoppssn -> hoppsan Rapport om okända ord + förslag sparas till fil UML-diagram Minst följande två klasser: SpellingWarning: innehåller information om upptäckta ev. stavfel (som t.ex. plats, ordet och förslag) Report: innehåller SpellingWarning-objekt
Laboration 7: filer ordfrekvensfiler /courses/tdde44/kursmaterial/laboration7/data några textfiler /courses/tdde44/kursmaterial/laboration7/texter
Skriva till fil
Öppna fil för läsa/skriva open(filename, mode) returnerar den öppnade filen som ett file-objekt. mode är en sträng vars defaultvärde är "r" som i "read" andra giltiga värden på mode är "w" som i "write" och "a" som i "append" read: vi kan endast läsa från filen write: vi kan endast skriva till filen, men existerande innehåll raderas append: vi kan endast skriva till filen, existerande innehåll sparas, nytt innehåll läggs till slutet på filen metoden file.write(s) skriver strängen s till filen file.
Exempel, skriva till fil # öppna fil för att lägga till text till datafile = open("filnamn.txt", "a") datafile.write("glöm inte bort") datafile.write("radbryt!\n") # stäng filen som vi öppnat datafile.close()
Kort om modulen argparse
Modulen argparse Inbyggd modul i Python för att underlätta hantering av olika typer av argument till skript. Till exempel flaggor med argument flaggor utan argument flaggor som har en lång form och en kort form, t.ex. -h och -- help obligatoriska och valfria argument Skapar också automatiskt hjälptext som fås om flaggan -h anges
Exempel 1, argparse #!/usr/bin/env python3 import argparse if name == ' main ': # skapa instans av ArgumentParser som bearbetar sys.args # OBS! sys behöver inte importeras parser = argparse.argumentparser() # be ArgumentPartser-objektet bearbeta argumenten till skriptet parser.parse_args()
Exempel 2, argparse #!/usr/bin/env python3 import argparse if name == ' main ': # skapa instans av ArgumentParser som bearbetar sys.argv # OBS! sys behöver inte importeras parser = argparse.argumentparser() # ange att vi vill lägga till ett positionellt argument med namnet "data_file" # och en viss hjälptext parser.add_argument("data_file", help="data file to load") # be ArgumentPartser-objektet bearbeta argumenten till skriptet # returnerar ett Namespace-objekt som innehåller argumenten som # instansvariabler args = parser.parse_args() # åtkomst till argumenten sker via instansvariabler med det namn vi angett # när vi skapade argumentet print("data_file: {}".format(args.data_file))
Exempel 3, argparse #!/usr/bin/env python3 import argparse if name == ' main ': # skapa instans av ArgumentParser som bearbetar sys.argv # OBS! sys behöver inte importeras parser = argparse.argumentparser() # ange att vi vill ange en flagga -n som får ett heltal som argument # argumentets värde ska sparas i instansvariabeln num och med # ett defaultvärde på 3 parser.add_argument("-n", dest='num', type=int, default=3) # ange att vi vill lägga till ett positionellt argument med namnet "data_file" # och en viss hjälptext parser.add_argument("data_file", help="data file to load") # be ArgumentPartser-objektet bearbeta argumenten till skriptet # returnerar ett Namespace-objekt som innehåller argumenten som # instansvariabler args = parser.parse_args() # åtkomst till argumenten sker via instansvariabler med det namn vi angett # när vi skapade argumentet print("data_file: {}".format(args.data_file)) print("num: {}".format(args.num))
Exempel 4, argparse #!/usr/bin/env python3 import argparse if name == ' main ': # skapa instans av ArgumentParser som bearbetar sys.argv # OBS! sys behöver inte importeras parser = argparse.argumentparser() # ange att vi vill ange en flagga -n som får ett heltal som argument # argumentets värde ska sparas i instansvariabeln num och med # ett defaultvärde på 3 parser.add_argument("-n", dest='num', type=int, default=3) # ange att vi vill spara resten av argumenten (minst ett) som vi kallar # FILE i hjälptexten i listan files parser.add_argument("files", metavar="file", help="file(s) to load", nargs="+") # be ArgumentPartser-objektet bearbeta argumenten till skriptet # returnerar ett Namespace-objekt som innehåller argumenten som # instansvariabler args = parser.parse_args() # åtkomst till argumenten sker via instansvariabler med det namn vi angett # när vi skapade argumentet print("files: {}".format(args.files)) print("num: {}".format(args.num))
Mer om argparse Tutorials https://docs.python.org/3/howto/argparse.html https://www.pythonforbeginners.com/argparse/argparse-tutorial Fullständig dokumentation https://docs.python.org/3/library/argparse.html Olika argument till add_argument-metoden https://docs.python.org/3/library/argparse.html#the-add-argument-method
Lite repetition
Beståndsdelar i ett program
Beståndsdelar i ett program värden (value): t.ex. siffror eller text (kallas för strängar) operatorer (operators): token/symbol som står för en instruktion variabler (variable): namngivna referenser till värden uttryck (expression): ett uttryck kan beräknas till ett värde (ibland säger man även utvärderas istället för beräknas) nyckelord (keywords): speciella ord som refererar till instruktioner som ska utföras skiljetecken (punctuators) sats (statement): fullständig instruktion
Hur kan nedanstående tolkas 1. a 2. a() 3. a(b) 4. a[b] 5. a.b 6. a.b() 7. a.b = c 8. a = b.c 9. a = b.c()
Klassdiagram med UML Enkelriktade associationer (vi använder oss endast av associationsrelationer i denna kurs) Bag känner till en instans av klassen Zipper. Zipper har rollen zipper i Bag Bag känner till en instans av klassen Container. Container har rollen container i Bag Zipper state : str = "open chance_to_break : float = 0.2 is_open() : boolean is_broken() : boolean open() close() try_to_break() zipper 1 Bag color : str = "green" open() close() add(item : str) container 1 Container items : list = [] capacity : int = 5 add(item : str)
Exempel många hus i en stad, befolkning
Exempel på aggregering City name : str add_house(house : House) get_population() : int houses 0..* House occupants : list = [] add_occupant(name : str) get_number_of_occupants() : int
Uppdelning av problem. Exempel på aggregering class City(object): def init (self, name): self.houses = [] self.name = name def add_house(self, house): self.houses.append(house) def get_population(self): total_population = 0 for house in self.houses: total_population += house.get_number_of_occupants() return total_population flaxtown = City("Linköping") house1 = House() house1.add_occupant("a") house1.add_occupant("b") flaxtown.add_house(house1) house2 = House() house2.add_occupant("c") flaxtown.add_house(house2) print(flaxtown) def str (self): city_str = "Name of city: {}\npopulation: {}" return city_str.format(self.name, self.get_population()) class House(object): def init (self): self.occupants = [] def add_occupant(self, name): self.occupants.append(name) def get_number_of_occupants(self): return len(self.occupants)
Exempel böcker i en bok-katalog
Exempel: Böcker i en bok-katalog Två egna klasser: Book, BookCatalogue Ett BookCatalogue-objekt kan innehålla flera Book-objekt BookCatalogue books 1 Book title : str = "Untitled"
books1.py # Exempel där BookCatalogue inte ansvarar för något class Book(object): def init (self, title="untitled"): self.title = title def str (self): return "<Book: '{}'>".format(self.title) class BookCatalogue(object): def init (self): self.books = [] def str (self): books_as_strings = [] for book in self.books: books_as_strings.append(str(book)) return "BookCatalogue: {}".format(", ".join(books_as_strings)) if name == " main ": bc = BookCatalogue() new_book = Book("Book 1") bc.books.append(new_book) new_book = Book("Book 2") bc.books.append(new_book) new_book = Book("Book 3") bc.books.append(new_book) print(bc)
books2.py # Exempel där BookCatalogue tar hand om logistik när nya böcker ska läggas till class Book(object): def init (self, title="untitled"): self.title = title def str (self): return "<Book: '{}'>".format(self.title) class BookCatalogue(object): def init (self): self.books = [] def create_and_add_book(self, title): new_book = Book(title) self.books.append(new_book) def str (self): books_as_strings = [] for book in self.books: books_as_strings.append(str(book)) return "BookCatalogue: {}".format(", ".join(books_as_strings)) if name == " main ": bc = BookCatalogue() bc.create_and_add_book("book 1") bc.create_and_add_book("book 2") bc.create_and_add_book("book 3") print(bc)
books3.py # Exempel där BookCatalogue tar hand om att ha koll på bok-id mha instansvariabel class Book(object): def init (self, book_id, title="untitled"): self.book_id = book_id self.title = title def str (self): return "<Book#{}: '{}'>".format(self.book_id, self.title) class BookCatalogue(object): def init (self): self.books = [] self.book_counter = 0 def create_and_add_book(self, title): new_book = Book(self.book_counter, title) self.book_counter += 1 self.books.append(new_book) def str (self): books_as_strings = [] for book in self.books: books_as_strings.append(str(book)) return "BookCatalogue: {}".format(", ".join(books_as_strings)) if name == " main ": bc = BookCatalogue() bc.create_and_add_book("book 1") bc.create_and_add_book("book 2") bc.create_and_add_book("book 3") print(bc)
books4.py (överkurs) # Exempel där Book tar hand om att ha koll på bok-id mha klassvariabel class Book(object): next_book_id = 0 def init (self, title="untitled"): self.book_id = Book.next_book_id Book.next_book_id += 1 self.title = title def str (self): return "<Book#{}: '{}'>".format(self.book_id, self.title) class BookCatalogue(object): def init (self): self.books = [] def create_and_add_book(self, title): self.books.append(book(title)) def str (self): books_as_strings = [] for book in self.books: books_as_strings.append(str(book)) return "BookCatalogue: {}".format(", ".join(books_as_strings)) if name == " main ": bc = BookCatalogue() bc.create_and_add_book("book 1") bc.create_and_add_book("book 2") bc.create_and_add_book("book 3") print(bc)
Exempel på utökning Flera böcker i bok-katalog Flera bok-kataloger i ett bibliotek... flera bibliotek i en biblioteksorganisation osv
Instans som huvudprogram
Skript med instans som "program" from books4 import * def get_user_confirmation(message, yes, no): user_input = "" while user_input not in [yes, no]: user_input = input("{} [{}/{}]: ".format(message, yes, no)) if user_input == yes: return True else: return False class BookApp(object): def init (self): self.commands = {} self.commands["ny"] = self.new_book self.commands["visa"] = self.show_books self.bookcatalogue = BookCatalogue() self.main() def show_books(self): print(self.bookcatalogue) def main(self): user_input = "" while user_input!= "q": user_input = input("vad vill du göra? ").lower() for command, cmd_func in self.commands.items(): if command == user_input: cmd_func() break if name == ' main ': BookApp() def new_book(self): while True: confirmed = "" title = input("ange boktitel: ") message = "Du skrev '{}', är det OK?".format(title) user_confirmation = get_user_confirmation(message, "j", "n") if user_confirmation: self.bookcatalogue.create_and_add_book(title) break else: print("ok, skriv in igen!")