Förra veckan tittade vi på olika programmeringsparadigmer och vad som skiljer dem åt. Nu är det onsdag igen, och läge att börja titta lite mer på just själva programmeringen!
Till att börja med vill man såklart kunna lagra information, data, när man programmerar. Man kanske behöver ha koll på hur många gånger man gjort en viss sak, eller vill lagra resultatet av en beräkning.
Datatyper
Några av de vanligaste datatyperna är följande:
- Int – Integer – Heltal : Lagrar ett heltal, positivt eller negativt. Hur stort tal som kan lagras beror på programmeringsspråk, hårdvara och i vissa språk kan man även specificera storlek.
- Float / Double – Flyttal : Lagrar decimaltal. Datorer lagrar tal med det binära talsystemet, vilket orsakar att avrundningsfel ofta förekommer med dessa. Det finns också Double, vilket är en Float med dubbelt så hög precision.
- String / Char – Strängar och tecken : Vill man lagra enstaka bokstäver/tecken, eller längre “strängar” (ord, meningar osv) görs detta smidigast med Char för tecken, och String för strängar. Ofta är en String en array med ett flertal Chars.
- Boolean – Sant/falskt : “Boolean” har, mig veterligen, ingen bra svensk översättning. Hur som helst lagrar den antingen sant eller falskt, så om man till exempel vill kolla om ett tal är större än ett annat, ges svaret ofta som en boolean.
- Array – lista : En array är egentligen bara en lista med en viss typ av objekt, och definieras ofta genom att man sätter “[]” efter den datatyp man vill ha en lista av. Till exempel int[] eller String[]. Denna lista kan man sedan modifiera och läsa av på olika sätt beroende på listtyp och programmeringsspråk.
När man skapar en instans av en datatyp kallas denna “variabel”. Värt att nämna är också att språken skiljer sig lite åt vad gäller att lagra värden. Javascript är till exempel inte typsäkert, vilket kallas dynamisk typning, så där kan man skapa en variabel och sen tilldela vilka typer av värden man vill, helt fritt:
var variabel; variabel = 1; variabel = "hej";
I detta fall skapar vi först variabeln “variabel”, tilldelar den sedan heltalsvärdet 1, och därefter tilldelar vi strängvärdet “hej”. Helt okej i Javascript.
Java däremot, är väldigt kinkigt och tillåter bara att en variabel tilldelas samma typ av värde:
int heltal; heltal = 1; heltal = "hej";
I detta fall skapar vi en integer, heltalsvariabel, med namnet “heltal”, och sätter den därefter till 1. Det går utmärkt. Den sista raden kommer däremot att spotta ut ett felmeddelande vid kompilering (dvs när koden omvandlas till maskinkod, som går fortare för datorn att köra), och denna avbryts.
Ännu ett exempel som hanterar detta på ett annorlunda och lite lustigt sätt är C++. C++ är ett väldigt kraftfullt språk på många sätt, men baksidan är att det är lätt att göra fel och svårt att hitta felen. Strängar i C++ är en variant av Char, vilket är typen som lagrar enstaka tecken. Varje tecken på en dator representeras av ett tal, och som exempel representeras ‘A’ av decimaltalet ’65’. Begrunda följande kod:
#include <iostream> using namespace std; int main() { char c = 65; cout << "Char c is: " << c << endl; c = 'A'; cout << "Char c is: " << c << endl; return 0; }
Här sätter vi värdet på ‘char c’ när vi skapar den, och sätter den då till heltalsvärdet 65. Detta motsvarar tecknet ‘A’, så raden under (som är C++ variant av utskriftsfunktion) kommer att skriva ut “Char c is: A”.
Sedan sätter vi c till ‘A’ (vi behöver ej skriva ‘char’ innan denna gång, eftersom variabeln redan existerar och ej behöver skapas en gång till, utan bara ändras). Den andra utskriften kommer således vara samma; “Char c is: A”.
Såna här finesser fungerar i C++, men huruvida det är bra eller inte får var och en själv avgöra. Klart är att ett relativt typsäkert språk bör vara att föredra för nybörjare, för att minska antalet potentiella felkällor.
Loopar och if-satser
Nu ska vi titta lite på loopar och if-satser, och då passar vi på att börja kika på Python! 😀
Men först ska vi titta på hur en loop och en if-sats ser ut i Java:
int i = 1; while (true) { if (true) { System.out.println("Iteration: "+i); } i++; }
Det finns olika typer av loopar, i detta exempel använder jag en “while”-loop. Den kör koden innanför sina klamrar/måsvingar så länge som villkoret (i detta fall, “true”) är sant. Man skulle istället för true kunna skriva exempelvis (i < 100) så kommer loopen att fortsätta tills heltalet i som definieras överst blir större än 99.
Den kod som finns inne i loopen, och som följdaktligen körs så länge loopen körs, är en if-sats som även den har villkoret “true”. Här kan man på samma sätt sätta in ett helt annat villkor som man vill ska gälla för att koden inuti if-satsen ska köras.
Inuti if-satsen har vi ett anrop som skriver ut “Iteration: “ följt av värdet på i, på skärmen. Sist men inte minst ökar vi värdet på i med ett, så att vi kan hålla koll på att vi nu är inne på nästa iteration. Sen körs if-satsen igen och igen!
Om vi nu ändrar koden litegrann, genom att dels köra while-loopen med det villkor jag beskrev ovan, och dels byta villkor i if-satsen till (i % 10 == 0), ett “modulo-villkor”, kommer if-satsen bara köras om i är jämnt delbart med 10, och while-loopen körs 99 gånger (och slutar när i är 100). Koden skulle då se ut så här:
int i = 1; while (i < 100) { if (i % 10 == 0) { System.out.println("Iteration: "+i); } i++; }
Därmed kommer alltså 9 utskrifter göras (för i = 10, 20, 30, 40, 50, 60, 70, 80, 90), medan det tidigare exemplet gör 99 utskrifter, en för varje iteration i loopen.
Notera också att det i if-satsen står dubbla lika med-tecken: if (värde == 0) { … }. Hur kommer detta sig? Jo, ett enkelt lika med-tecken används för tilldelning, alltså när man vill ändra värdet på en variabel.
Vi vill såklart inte göra det i en if-sats, för där vill vi ha ett svar på om något är sant eller falskt och inte ändra värdet på en variabel. Visst? Precis. Java tillåter heller inte att man har ett enstaka lika med-tecken i if-satser, då blir det kompileringsfel.
Men C++ då, detta allsmäktiga och oändligt kraftfulla språk? Där får man tilldela ett värde till en variabel i en if-sats, om man vill. Det skulle alltså se ut så här:
#include <iostream> using namespace std; int main() { int i = 1; if (i = 2) { i++; } cout << "Value of i is: " << i << endl; return 0; }
Vi sätter heltalet i till 1, och i if-satsen tilldelar vi i värdet 2. Vad tror du värdet på i är när utskriften sker? Om du gissade på 3 så var det rätt. När man tilldelar ett värde i en if-sats, returnerar operationen ett värde och detta tolkas av språket som sant eller falskt. I fallet med int tolkas 0 som falskt, och allt annat som sant så (i = 2) gör att if-satsens innehåll körs medan (i=0) inte kör innehållet. Detta kan man säkert dra nytta av i vissa situationer, men är det snyggt och läsligt? Nja.
Python
För att då övergå till Python, så är det ett interpreterat högnivåspråk, vilket innebär att koden inte kompileras om till maskinkod innan det körs, utan istället körs direkt, rad för rad. Detta är långsammare än att först kompilera koden (speciellt om koden ska köras flera gånger), eftersom översättningen från skriven kod till maskinkod måste göras om varje gång raden anropas. Python är också smidigt att använda som skriptspråk. Ett skript är en samling kodrader som körs utan användarinteraktion.
I vårt tidigare exempel med Java kanske du la märke till klamrarna/måsvingarna: { } . I fallet med if-satsen betyder dessa att allt inom dessa klamrar (System.out.println() ) ska köras om if-satsen är sann, så lägger man fler anrop inom klamrarna körs även dessa. Java bryr sig inte om formateringen i övrigt när koden kompileras, så i teorin skulle man kunna skriva all koden ovan på en rad, förutsatt att semikolon och klamrar bibehålls. Detta går dock emot Javas kodstandard, vilken man bör följa för att skriva så läsbar kod som möjligt!
Så fungerar inte Python. I Python är kodformateringen av yttersta vikt! Där finns nämligen inga klamrar eller semikolon, utan istället utnyttjas radernas indentering, eller “framflyttning”, för att avgöra var och när en kodrad ska exekveras. För att illustrera hur lätt det är att göra fel, se följande exempel:
boolean = false if (boolean): print("hej") print("hopp") boolean = false if (boolean): print("hej") print("hopp")
Dessa två if-satser är snarlika, så när som på framflyttningen på det sista “print()”-anropet. Vad som händer är att i det första exemplet är boolean falsk, och därför körs inte if-satsen och ingenting skrivs ut då båda print()-anropen står ett steg längre in än if-satsen, och därför antas tillhöra den.
I det andra exemplet gäller samma sak, men eftersom det andra print()-anropet saknar indentering och står på samma nivå som if-satsen anropas den först efter att if-satsen har gåtts igenom och det gör att “hopp” skrivs ut på skärmen.
Detta gör att det är lättare att göra fel, och det blir även fel om kodraderna står ett steg för långt in, men å andra sidan är koden ganska lättläst när man skrivit rätt eftersom så få onödiga tecken finns med och man är tvungen att följa kodstandarden (till en viss gräns).
Varför ska man då välja just Python, om det exekveras långsammare än vissa andra språk? Jo, Python är smidigt att koda då det finns många “genvägar” man kan utnyttja för att skriva så lite kod som möjligt, till exempel när man arbetar med arrayer (listor). Dessutom har det fullt stöd för objektorienterad programmering, men det går även hur smidigt som helst att programmera både funktionellt och imperativt vid behov. Och framför allt…
Python är hur smidigt som helst på Raspberry Pi 🙂
Nu lovade jag i förra inlägget att vi skulle titta på import av bibliotek i detta inlägg, men det sparar vi till nästa vecka. Blir på tok för mycket text annars. Utöver det börjar vi kika lite på enklare Python-program och att arbeta mot GPIO-porten. Håll ut så länge! 😀
Uppdatering: Nu finns nästa avsnitt uppe här!
Kul att du gillar vår blogg!
Skriv upp dig på vår maillista för att få allt det senaste från m.nu - Nya produkter, kampanjer och mycket mer!
Wohoo! Du är nu med på maillistan!