Använda Python Laboration 1 GruDat, DD1344 Örjan Ekeberg 14 oktober 2008 Målsättning Målet med denna laboration är att du ska prova på att använda Python, framförallt interativt. Du ska också lära dig hur man kör pythonprogram lagrade i filer. Du ska bli bekant med datatyperna strängar och listor samt skriva enkla funktioner som hanterar dessa. Du ska slutigen prova ett verktyg för automatisk testkörning av programdelar, s.k. unit testing. 1 Innan du börjar Här introducerar vi några generella hjälpmedel för labbarna. Detta förutsätter att du använder datorerna i datorsalarna. Om du vill kan du installera Python på din egen dator, men du måste ändå göra incheckningen enligt nedan på en salsdator. 1.1 Inställningar Börja med att ge kommandot course join grudat08. Detta gör att vissa inställningar görs i din miljö för att passa kursen. Till exempel får du tillgång till rätt version av Python. Pröva också course help. Om du ska labba ihop med en kompis som råkar ha kontonamnet u1pnyxtr kan course labdir grudat08 u1pnyxtr vara lämpligt. Se till att din labbkompis på sitt konto gör motsvarande kommando med ditt användarnamn. Ni kommer då att få en gemensam katalog grudat08 där ni kan spara alla program ni skriver i kursen. Skapa gärna en underkatalog lab1 under grudat08 där du sparar de filer som har med första labben att göra. 1
1.2 Incheckning För att kunna få labbresultat inrapporterade måste alla som följer kursen checka in i res-systemet. Skriv kommandot res checkin grudat08 och svara på frågorna om personnummer och studiestatus. Frågan om numret på övningsgruppen besvarar du med det labbpass du just nu deltar i. Under kursen kan du med kommandot res show grudat08 kolla att dina labbar har blivit rapporterade. 1.3 SimaManager SimaManager är ett program som hjälper handledarna att hålla reda på vem som står i tur att få hjälp under labbpassen. Kommandot sm startar hjälpköhanteraren. Eventuellt måste du först göra module add sima. 2 Pythontolken Kommandot python startar pythontolken i interaktivt läge. I den interaktiva pythontolken kan du direkt skriva pythonuttryck. Dessa beräknas och svaret skrivs ut i terminalfönstret, ungefär som i Matlab. Interaktiv körning av pythontolken gör det lätt att prova idéer och att testa sina program. $ python >>> 17 17 289 >>> x=17 >>> 5 x 2+2 x 10 1478 >>> def f ( x ) : return 5 x 2+2 x 1 >>> f (17) 1478 >>> t e s t p u n k t e r = [ 0, 0. 5, 1. 0, 2. 0 ] >>> for x in t e s t p u n k t e r : print f ( x ) 1 1.25 6. 0 23.0 >>> def dubbla ( x ) : return x+x >>> dubbla (17) 34 2
>>> dubbla ( o j ) o j o j >>> dubbla ( dubbla ( o j ) ) o j o j o j o j >>> <Ctrl D> $ Nackdelen med det interaktiva användingssättet är att allt du skriver går förlorat. Du kan alltså inte rätta fel eller fortsätta programmera på något du inledde igår. Detta är naturligtvis helt ohållbart för annat än mycket små program. Normalfallet är därför att man skriver sina program i en fil med någon lämplig texteditor, t.ex. Emacs. Program lagrade i en fil, säg exempel.py, kan köras på två olika sätt. Enklast är att man anger filnamnet på kommandoraden: python exempel.py. Programmet i filen kommer då att köras icke-interaktivt. Ofta vill man dock arbeta interaktivt med sitt program och då är det bättre att importera programmet från den interaktiva pythontolken: $ python >>> import exempel >>> exempel. dubbla (17) 34 Lägg märke till att funktionen nu heter exempel.dubbla. Det beror på att Python håller reda på varifrån alla variabler och funktioner kommer med hjälp av moduler. När man använder import skapas en modul med samma namn som filen. Tips: Om man tycker att det blir jobbigt att skriva ut modulnamnet varje gång kan man ge modulen en kortnamn: >>> import exempel a s x >>> x. dubbla (17) 34 Tips: Det är också möjligt att importera allt som definieras i en fil utan att det hamnar i en modul: >>> from exempel import >>> dubbla (17) 34 Det finns dock några nackdelar med detta arbetssätt. Om man importerar från flera olika filer finns risken att samma funktions- eller variabelnamn används på flera ställen. Detta kan leda till svårfunna fel. En annan nackdel är att man inte kan använda sig av nästa tips. 3
Tips: Om man ändrar i filen räcker det inte att göra import på nytt. Det beror på att pythontolken redan anser att filen är importerad. För att tvinga tolken att ladda en modul på nytt använder man funktionen reload: >>> import exempel >>> r e l o a d ( exempel ) Notera: Laborationerna är anpassade till Python version 2.5. En av de stora ändringarna (iallafall ur ett svenskt perspektiv) i nästa version av Python, Python 3.0, är att hanteringen av icke-anglosaxiska tecken blir betydligt enklare och mer naturlig. Det gäller alltså alla texter som innehåller t.ex. Å, Ä, och Ö. Om inget oförutsett händer kommer Python 3.0 att släppas redan innan kursen är slut. Det är därför ingen större mening med att lära sig hur man hanterar svenska tecken i Python 2.5 (det är lite småtrixigt). För att kringgå problemet kommer vi därför helt enkelt att undvika texter med Å, Ä och Ö. 3 Strängar och listor Python har flera inbyggda datatyper. Vi börjar med att bekanta oss med strängar och listor. Strängar används för att representera text medan listor kan innehålla sekvenser av olika slag. 3.1 Strängar Prova interaktivt att göra operationer på strängar. Här är några förslag, men experimentera gärna själv: >>> a = H e llo world >>> a [ 0 ] >>> a [ 6 ] >>> a [ 0 : 5 ] >>> w in a >>> x in a >>> l e n ( a ) >>> a. upper ( ) >>> a. s p l i t ( ) >>> a + l i n g Prova också att använda help-funktionen. Den är speciellt användbar om man skickar med en funktion som argument: 4
>>> help ( l e n ) >>> help ( a. upper ) >>> help ( hej. upper ) 3.2 Listor Listor innehåller sekvenser av dataelement. Det kan vara en sekvens av tal, strängar, m.m. Alla element behöver inte vara av samma typ; ett tal kan alltså följas av en sträng o.dyl. Det är t.o.m. möjligt att ha listor som element i listor! Detta kommer vi att utnyttja senare när vi vill bygga komplicerade datastrukturer. Det enklaste sättet att skapa en lista är att räkna upp elementen mellan ett par av hakparenteser, ungefär som man skapar vektorer i Matlab: >>> x = [ 1 7, 4711, 3. 1 4 1 5, 2. 7 1 8, 1 7 ] >>> y = [ one, two, t h r e e ] Precis som för strängar finns det en uppsjö av inbyggda operationer man kan göra på listor. Här är ett smakprov: >>> x [ 2 ] >>> y [ 1 ] = hoppsan >>> y. append ( 4 ) >>> l e n ( y ) >>> x. count ( 17) >>> x. s o r t ( ) >>> one in y Lägg märke till att många operationer är gemensamma för strängar och listor. Detta är medvetet gjort, båda datatyperna är vad som i Python kallas sekvenser. for-loopar i Python stegar t.ex. alltid igenom en sekvens. Prova och förklara med egna ord vad dessa satser gör: >>> names = [ Anna, Lotta, P e l l e, Johan ] >>> for x in names : print x >>> for x in H e l l o world : print x >>> for x in Anna Lotta P e l l e Johan. s p l i t ( ) : print x >>> for x in [ Lotta, Sven, Peter ] : i f x in names : 5
print x Lägg märke till hur man skriver sammansatta satser i Python. Till skillnad från många andra programmeringsspråk är indenteringen, d.v.s. indraget från vänsterkanten, betydelsefullt. Lägg också märke till det kolon som avslutar raden vid for och if. Samma princip gäller även för andra sammansatta satser. 4 Skriva program Du ska nu använda Emacs, eller någon annan texteditor om du föredrar det, för att skriva ett pythonprogram i en fil. Kalla filen exempel.py, där.py gör att verktygen behandlar filen som python-källkod. Låt oss börja med att definiera en funktion som räknar antalet tecken i en sträng: def s t r i n g l e n g t h ( s ) : count = 0 for x in s : count += 1 return count Om du har gjort rätt så bör denna funktion ge samma resultat som den inbyggda len-funktionen. Prova att så verkligen är fallet. Vad händer om du använder stringlength på annat än strängar? Prova med listor, tal och annat du kan komma på. Vad händer om du skriver help(stringlength)? Jämför med help(len). Försök få din funktion lika väldokumenterad som den inbyggda. Tips: Om första satsen i en funktionsdefinition är en strängkonstant så betraktas den som dokumentation för funktionen. Tips: Man kan skriva strängar som sträcker sig över flera rader om man omger dem med tre apostrofer ( ) eller tre citattecken ("""). Du ska nu författa några egna funktioner som använder sig av operationerna ovan. 4.1 Hitta långa ord Skriv en funktion som tar två parametrar, en lista med strängar och ett tal, och returnerar en lista med alla strängar som är längre än talet. Den ska alltså fungera så här: 6
>>> import exempel >>> exempel. longwords ( [ Goodbye, my, dear ], 3) [ Goodbye, dear ] 4.2 Tag bort dubbletter Skriv nu en funktion som tar en lista med strängar som parameter och returnerar en lista med alla dubbletter borttagna. Exempel: >>> import exempel >>> exempel. unique ( [ to, be, or, not, to, be ] ) [ to, be, or, not ] Tips: Skapa en tom lista och använd append för att lägga in de ord som inte redan finns i listan. Om du inte gjort något konstigt så ska din funktion utan vidare klara av listor som innehåller annat än strängar. Prova! >>> exempel. unique ( [ 1, 3, 5, 4, 3, 2, 1 ] ) [ 1, 3, 5, 4, 2 ] 4.3 Dela upp och sätta samman strängar Som du sett kan man använda split för att dela upp en sträng i en lista av ord. Split delar vid alla mellanrum (om man inte anger något annat). Att sätta samman strängar är lika enkelt, men inte lika uppenbart. Strängar har metoden join som tar en lista med strängar som parameter. Ursprungssträngen används som avskiljare mellan strängarna i listan. Detta blir kanske klarare efter ett par exempel: >>> hej. j o i n ( [ Allan, t a r, kakan ] ) A l l a n h e j t a r h e j k a k a n >>>. j o i n ( [ a t t, vara, e l l e r, i n t e, vara ] ) att vara e l l e r inte vara >>>. j o i n ( [ H e l l o, world ] ) H e l l o world Använd din nyvunna insikt för att konstruera en funktion som tar en sträng besående av flera ord och returnerar en sträng där alla dubblettord är borttagna. Anropa funktionen som du skrev i förra steget för att göra själva dubblettborttagningen. 7
5 Automatisk testkörning När man skriver stora program är det viktigt att förvissa sig om att varje del är korrekt innan man går vidare och använder den. Det interaktiva arbetssättet i Python gör det enkelt att provköra varje funktion eller modul för sig. Så fort man ändrat något i en funktion eller en modul finns alltid risken att ett fel smugit sig in. Man bör därför göra om alla tester efter varje ändring. Python, och många andra moderna programutvecklingsmiljöer, har hjälpmedel för att automatisera testkörningen. Ofta kallas detta unit testing. Vi ska här introducera en förenklad variant av unit-testing: doctest. doctest bygger på att man skriver körexempel inbakat i dokumentationssträngen till funktioner, klasser eller moduler. doctest letar reda på alla rader som inleds med >>> och kontrollerar att resultatet blir det rätta. Antag att vår fil exempel.py innehåller följande definition: def r e v s t r i n g ( s ) : Reverses a s t r i n g. For example : >>> a = H e l l o world >>> r e v s t r i n g ( a ) dlrow o l l e H >>> r e v s t r i n g ( r e v s t r i n g ( a ) ) H e l l o world return s [ : : 1 ] Vi kan nu provköra alla funktioner i filen genom: >>> import exempel >>> import d o c t e s t >>> d o c t e s t. testmod ( exempel ) ( 0, 3) De två returnerade talen (0 och 3 i detta fall) anger hur många tester som blev fel och hur många som kördes. För att se exakt vad som händer kan du skriva doctest.testmod(exempel, verbose=true). Ändra funktionen så att den ger fel svar och kontrollera att doctest verkligen upptäcker felet. Komplettera nu dina egna funktioner med tester för doctest och kontrollera att allt fungerar enligt dokumentationen. 8
När du är klar med laborationen: redovisa för en handledare och se till att få en kvittens här. Ditt namn:. Handledarens signatur:. Dagens datum: GruDat 2008, Laboration 1 9