Firewalls: Iptables SQL Injection voor beginners
Jun 02
    Change language to :

 

——————————-
Leren Programmeren met Python
——————————-

Datum: 29/08/2003
Versie: 1.0
Auteur: Vincent “gorny” Berg

Onderdeel van de Mostly-Harmless Knowledge Base

Dit document mag vrijelijk verspreid worden op voorwaarde dat de informatie
hierin niet wordt gewijzigd.

- Voorwoord
- Introductie
- Opzet van een programmeertaal
- Beginselen van het programmeren
- “Flow control”
- Functies in Python
- Je vriendjes
- Afsluiting
- Literatuur

- Voorwoord

Dit document handelt over de beginselen van het programmeren en is vooral geschikt voor mensen die totaal geen programmeerervaring hebben. Eenieder die echter al veel ervaring heeft zal met dit document toch snel de basis dingen van Python onder de knie hebben om vervolgens snel grote scripts en/of applicaties te gaan ontwikkelen in deze prachtige taal.
Python is een “agile” programmeertaal. Dit betekent volgens het woordenboek dat het snel, lichtgewicht is en er betrekkelijk makkelijk veranderingen in aan te brengen zijn. Door de betrekkelijk eenvoudige syntaxis wordt een beginnende programmeur niet afgeleidt met “onnodige” zaken en kan deze snel functionele dingen leren. [1]
Ik hoop dat de lezer veel plezier heeft aan dit document. Voor vragen, opmerkingen en/of aanvullingen kan er altijd contact met mij worden gezocht via het Mostly-Harmless forum of het IRC-kanaal.

- Introductie

Veel introducties tot het programmeren beginnen simpelweg met een zogeheten “Hello World” programma. Het enige wat dit doet is het laten zien van de tekst “Hello World” op het scherm. Echter mijn tekst is (nog) niet meteen gericht op het programmeren, maar heeft tot doel de lezer de edele kunst van het programmeren beter te laten begrijpen.
De meeste (conventionele) programeertalen zijn opgebouwd volgens een vaste structuur. Ze bestaan allemaal uit syntaxtische en grammaticale regels waaraan voldaan moet worden door de programmeur. Dit is lang niet zo moeilijk als het klinkt. Bij de syntaxis gaat het (simpel gezegd) om de opbouw van de “woorden” waaruit de programmeercode bestaat. Vergelijk het met de Nederlandse taal. Daarbij moet het woord “appel” ook geschreven worden als “appel” en niet als “appul”.
De grammatica van een programmeertaal zijn een verzameling van regels die beschrijven hoe de “zinnen” in een programmeertaal worden opgebouwd. Ook hierbij is weer mooi de parallel te trekken met de Nederlandse taal. “Hee meneer, doe mij maar een zak met appels!” is grammaticaal correct, terwijl een “He meneer, doe ik een zak maar met appels!” grammaticaal incorrect is. Voor de groenteboer is het dan ook moeilijk te begrijpen wat de klant wil indien hij/zij geen zinnen maakt die niet voldoen aan de grammaticale en syntaxis-regels van de Nederlandse taal.
De metafoor voor het programmeren (de communicatie met de groenteboer) moet nu wel duidelijk zijn. Het verschil bij het programmeren is dat men meestal communiceert met een “compiler” of een “interpreter”. Deze controleren de code van de programmeur op fouten in de syntaxtische en grammaticale regels. Een “compiler” (lees: vertaler) zal de programmeercode daarna omzetten naar een “executable” zodat de gebruiker dat bestand kan uitvoeren, terwijl een “interpreter” de code interpreteert en meteen uitvoerd.
Om weer even terug te komen op Python; het is een geinterpreteerde taal. Er zijn wel manieren om executables van je code te maken, maar die werken erg slecht en maken je programma enorm traag en veel groter dan nodig is. Dus om in Python te kunnen programmeren heb je eigenlijk alleen maar de “interpreter” nodig en die is beschikbaar voor (bijna) elk platform. [2]

- Opzet van een programmeertaal

Programmeren bestaat uit het in een editor (VIM, emacs, UltraEdit, joe) typen van programmeercode. Deze code bestaat uit allerlei bewerkingen, veelal op variabelen. Variabelen zijn niets meer dan een stukje geheugen waarin een bepaalde waarde kan worden geplaatst. Net als de groenteboer die plastic zakjes gebruikt om het fruit en de groente in te doen zal de programmeur dus variabelen gebruiken om zijn dingen in te stoppen.
Er zijn echter verschillende soorten variabelen. Zo zijn er “chars” die ruimte hebben om precies 1 karakter (ASCII) in op te slaan. Dan zijn er “ints” (integers of reals) waarin een geheel (!!) getal tussne 0 en 2^32 kan worden geplaatst. Bij “floats” kan de programmeur een getal met decimalen achter de komma op slaan en dan zijn er natuurlijk ook nog de “strings” die gewoon een opeenvolging van karakters bevat. Een “string” die je zou kunnen opslaan zou deze zin bijvoorbeeld kunnen zijn. Vaak kan een programmeur eigen datatypes gebruiken ( vooral bij het object-georienteerde programmeren) is dat handig. Dit is voorlopig nog niet aan de orde aangezien dit document echt over de beginselen van het programmeren handelt.
De opzet van vele programmeertalen is om code te kunnen hergebruiken. Een programmeur wil niet bijvoorbeeld tien keer een x aantal regels typen om een bepaalde actie te kunnen verrichten. Vergelijk dit met de groenteboer. Deze heeft ook niet 10 kassa’s voor 10 verschillende klanten met daarachter 10 kassameisjes. De groenteboer zorgt heeft gewoon 1 kassa met 1 kassameisje en die wordt gebruikt door alle klanten. Dit kun je weer zien als een metafoor met het programmeren. Een stuk code (de kassa) wordt door verschillende andere stukken code (de klanten / het kassameisje) gebruikt.
In de programmeertaal noemt men zo’n stuk code ook wel een functie. Vaak worden er “variabelen” meegegeven aan een functie (zoals je het zakje met fruit aan het kassameisje geeft zodat die het weegt). Nadat dat gebeurd is zal de interpreter verder gaan waar ze gebleven was.

- Beginselen van het programmeren

Als het goed is hebben we nu een beetje een idee hoe een programeertaal is opgebouwd. Om ervoor te zorgen dat onze code wordt uitgevoerd moet deze syntaxtisch en grammaticaal correct zijn. Om er bovendien voor te zorgen dat we data kunnen opslaan hebben we dus variabelen en functies nodig. We zullen nu (eindelijk) eens wat dingen gaan proberen in Python. Hierbij wordt ervan uitgegaan dat de lezer Python heeft geinstalleerd [2] en de interpreter heeft opgestart. Dit wijst zich erg vanzelf. Onder Windows wordt alles automatisch geinstalleerd en kun je Python gewoon opstarten door in het Startmenu te kijken. Voor elke *nix is het echter anders en dat zal ik niet gaan behandelen. De informatie op de website is redelijk duidelijk en bovendien heeft bijna elke distributie Python standaard geinstalleerd of het is heel makkelijk om dat met het desbetreffende package-managementsysteem te installeren.
Als men de interpreter opstart krijgt men als het goed is een “prompt” voor de neus. Hierin kan je allerlei commando’s typen. Zodra je echt grotere programma’s gaat schrijven is het makkelijker om de meegeleverde Python editor (IDLE) te gebruiken waarin je alles op kan slaan als een file zodat je niet alles elke keer overnieuw hoeft te typen.

gorny@sethanon:~$ python
Python 2.1.3 (#1, Sep 7 2002, 15:29:56)
[GCC 2.95.4 20011002 (Debian prerelease)] on linux2
Type “copyright”, “credits” or “license” for more information.
>>> x = 2
>>> print x
2
>>>

Zoals men ziet heb ik hier een variabele gemaakt genaamd “x”. Deze variabele geef ik de waarde 2. Let op! Het werkt dus anders dan bij de wiskunde waarbij een a = b betekent dat a gelijk is aan b. In het programmeren wordt er bedoeld dat in de variabele x (het plastic zakje dus) de waarde 2 (appels?) wordt gestopt. Met het commando print x wordt dan de waarde getoond. Hieronder zullen nog wat voorbeelden gegeven worden van de andere soorten variabelen.

>>> x = 1.345
>>> print x
1.345
>>> x = ‘A’
>>> print x
A
>>> x = ‘appels zijn het lekkerst van de groenteboer’
>>> print x
appels zijn het lekkerst van de groenteboer
>>>

Zoals we zien heb ik eerst een “float” gecreeerd en daarna een “char”. De code eindigt met maken van een “string”. Het mooie van Python is dat het “dynamisch getypeerd” is. Zoals we zien hebben we niet elke keer mee moeten geven aan de variabele x WAT we erin gaan stoppen (een groenteboer vertelt ook niet aan het zakje dat hij er appels in gaat stoppen). Bovendien kan je later gewoon iets totaal anders in de variabele stoppen (zo werkt elke zichzelfrespecterende plastic zak immers ook). Let op! Bij de strings in Python (en de chars) is het ook mogelijk om ze te omgeven met een ” in plaats van een ‘. Dit heeft echter verder totaal geen effect. De variabelenaam x noemen we een “identifier”. De interpreter identificeert hiermee de variabele. Alles moet een naam hebben omdat we het anders niet zo makkelijk kunnen gebruiken.

>>> x = t
Traceback (most recent call last):
File “<stdin>”, line 1, in ?
NameError: name ‘t’ is not defined

Wat gebeurd er nu? We hebben geprobeerd aan x de variabele t toe te wijzen. Maar aangezien we de variabele t nog niet gedefinieerd hebben kan de interpreter hier niets mee.

>>> t = 3
>>> x = 2
>>> print t, x
3 2
>>> x = t
>>> print t, x
3 3

Ook dit stukje code is erg simpel. We hebben twee plastic zakjes genaamd x en t. In x zitten 2 appels en in t zitten 3 appels. Nu zorgen we ervoor dat er evenveel appels in x als in t komen te zitten.

>>> x = 3
>>> t = 5
>>> x + t
8
>>> print x
3
>>> x = x + t
>>> print x
8

Ook dit is erg duidelijk. We hebben twee variabelen genaamt x en t en die tellen we bij elkaar op. Bij de eerste keer optellen komt er 8 uit maar de variabelen x en/of t worden niet veranderd. Bij de tweede keer tellen we echter x en t bij elkaar op en dat resultaat wordt in x gestopt. De interpreter werkt dus van rechts naar links. Bij de wiskunde zou dit heel anders werken. Dan zou er uit volgen; x = x + t –> x-x = t –> 0 = t –> t = 0.

- “Flow control”

We gaan ons nu met iets anders bezig houden. Zoals we weten begint de interpreter bovenin het bestand en voert daarna alles rechttoe rechtaan uit. Maar met de technieken die vallen onder de “Flow control” oftewel de controle over hoe het programma uitvoert (flowed) kunnen we dit wat aanpassen. Hiervoor gebruiken we bijvoorbeeld de if/else/while/for “statements”. Een statement is in feite niets meer dan een bewering die door de interpreter wordt uitgevoerd.
Bij het programmeren worden echter ook expressies gebruikt. Deze kunnen maar twee waardes hebben genaamd True of False (sommige programmeertalen hebben ook booleans waaronder Python die zo’n type representeren). Voor True of False (lees: Waar / Niet-Waar) worden ook vaak de waarden 1 en 0 gebruikt. Dit kunnen we illustreren met het volgende voorbeeld.

>>> print x
3
>>> x == 3
1
>>> x == 2
0

Let op! Er wordt nu een dubbele = gebruikt. Met 1 “isgelijkteken” zouden we immers de variabele x een nieuwe waarde toe gaan wijzen en dat was niet de bedoeling. Zoals we zien valideert de eerste expressie. x heeft namelijk de waarde drie en dus is die expressie gelijk aan 1 (waar). De tweede expressie valideert niet want x is NIET gelijk aan 2 maar aan 3 en dus is die expressie gelijk aan 0 (niet-waar). Het is dus zaak altijd erg goed op te letten waarna je met een expressie bezig bent of met een statement aangezien het rare fouten op kan leveren als je het verkeerde aantal isgelijktekens gebruikt.

>>> x = 4
>>> if x == 4:
… print ‘er zitten 4 appels in de zak’
… else:
… print ‘er zitten meer of minder dan 4 appels in de zak’

er zitten 4 appels in de zak

Bij het voorgaande stukje code wordt het inspringen bij de “print” statements gedaan door de TAB toets. Let hierbij op. Python kent niet, zoals andere talen, haakjes of accolades om “blokken” af te sluiten. Door naar het aantal TABS te kijken weet de interpreter (of de programmeur) welk stukje code waarbij hoort. Dus alles dat naar het eerste “if” statement komt en begint met een TAB behoort nog onder dat if-statement en zal dus uitgevoerd worden als de expressie “x == 4″ wordt gevalideert (dus waar is). We kunnen echter ook andere tekens gebruiken zals <, > en !=. De eerste staat voor kleiner dan, de tweede voor groter dan en de derde voor “isongelijkaan”.

>>> x = 6
>>> if x > 4:
… print “x is meer dan 4″
… elif x < 2:
… print “x is minder dan 2″
… elif x != 3:
… print “x is ongelijk aan 3″

x is meer dan 4

Let op! Het “elif” statement staat alleen maar voor de afkorting van “else if”. Hierdoor kan je dus meerdere condities valideren met een serie van if statements. Maar waarom wordt er niet geprint dat x ongelijk is aan 3? Dat komt omdat de if en de 2 elifs bij elkaar horen. Zodra er 1 expressie als WAAR wordt geevalueerd dan zal de interpreter de rest van het blok overslaan en verder gaan waar hij gebleven was.

>>> x = 6
>>> if x > 4:
… print “x is meer dan 4″
… elif x < 2:
… print “x is minder dan 2″
… if x != 3:
… print “x is ongelijk aan 3″

x is meer dan 4
x is ongelijk aan 3

Zoals we zien wordt er nu een nieuw if-blok gemaakt waardoor de interpreter het nu wel mee zal nemen en dus wordt het bericht dat x ongelijk aan drie is ook getoond. Er kan bij een if-blok altijd maar 1 ifstatement gebruikt worden, waarna er een (in theorie) oneindig aantal elif statements kan volgen met als afsluitend een else statement. Dit hoeft echter niet. Een if-statement kan ook gewoon op zichzelf staan.

>>> i = 5
>>> while i > 0:
… print i
… i = i - 1

5
4
3
2
1

Dit is een voorbeeld van het gebruik van een while-lus. Deze voert eigenlijk net zolang alles in het while-blok uit zolang de expressie i > 0 geldt. Hierbij moet je dus erg oppassen. Zou je de “i = i - 1″ vergeten dan zou de interpreter eeuwig in het blok blijven zitten en continu 5 op het scherm printen en nooit meer verder gaan met de rest van het programma. Het is dus belangrijk om er voor te zorgen dat je altijd uit de lus kan “springen”.

>>> for i in range(0, 5):
… print i

0
1
2
3
4

Een ander voorbeeld is de for-lus. Hierbij hoeft de i niet eerst gedeclareerd te worden. Dit doet de range() functie voor je. Het enige wat er hier gebeurd is dat de range begint bij 0 en daarna 5 stappen doet. Hierdoor wordt het getal 5 ook niet op het scherm geprint. 0-4 zijn immers vijf getallen.

>>> for i in range(0, 4, 2):
… print i

0
2

Met de for-lus en de range functie kun je ook de grootte van de stapjes aangeven die gedaan moeten worden. Het werkt eigenlijk erg intuitief en makkelijk. De for-lus werkt op deze manier wel anders dan in andere programmeertalen maar dat heeft met het objectgeorienteerde karakter van Python te maken. Voor de beginner is dit voldoende om te weten en hij/zij kan dan ook genoeg met deze lussen uitvoeren.

- Functies in Python

We gaan het nu eindelijk hebben over functies. De eerste zijn we al tegengekomen (de range() functie) die twee of drie variabelen aankan. Het is nu handiger om een editor te gebruiken (notepad is al voldoende) omdat we nu wat meer code gaan produceren. Het bestand waarin je alles getypt hebt sla je op en voer je daarna uit door iets ala: “gorny@sethanon:~$ python file.py” te typen. Voor Windows gebruikers is het een kwestie van het bestand opslaan met de extentie .py en daarna erop te dubbelklikken. De mensen die IDLE (van harte aanbevolen, draait onder bijna elk platform) gebruiken kunnen gewoon de code bewerken, op slaan en dan op Control-F5 drukken om hun code uit te voeren.
Functies hebben in Python, net zoals variabelen een bepaalde “identifier” oftewel een naam. Deze naam moet (net zoals bij variabelen) uniek zijn. Bovendien zit er een verschil tussen hoofd- en kleine letters. Een functienaam mag ook niet hetzelfde zijn als een variabelenaam. Doet de programmeur dit toch dan zal op dat moment de naam naar de functie verwijsen en niet meer naar de variabele. In het omgekeerde geval geldt precies hetzelfde. Een functie in Python definieer je met het “keyword” def. Deze sleutelwoorden (net zoals if/else) mogen natuurlijk niet als functienaam of variabelenaam gebruikt worden anders zou de interpreter het enorm moeilijk krijgen om de code nog uit te voeren.

>>> def telop(a, erbijop):
… return a + erbijop

>>> print telop(2, 3)
5

Wat doet dit stukje code? Het roept de functie telop aan. Zoals te zien is accepteert de telop() functie twee verschillende variabelen genaamd a en erbijop. De functie telt “a en erbijop” op en retouneert dat getal. Het print statement doet niets meer dan het print van het “antwoord”. De waardes die aan telop() worden meegegeven worden in de variabelen a en erbijop geplaatst. Een functie in Python hoeft echter niet expliciet te returnen. Als dat niet gebeurd (of er staat een return statement met verder geen waarde erachter) dan retouneert de functie simpelweg None.

>>> def test(start=1, end=5):
… for i in range(start, end):
… print i

>>> test()
1
2
3
4
>>> test(2, 3)
2
>>> print test(0, 0)
None

In dit voorbeeld gebruiken we een functie test die de waarden in de range van “start” tot “end” afdrukt. Het mooie van Python is dat we standaard (”default”) waarden mee kunnen geven. Zodra we dus geen variabelen meegeven aan de functie test() dan zal deze gewoon de standaard waarden voor start en end nemen en daarmee rekenen. De allerlaatste regel laat zien wat test() retouneert, namelijk None.

- Je vriendjes

Elke programmeur heeft vriendjes. Veel vriendjes. Daaronder valt onder andere je editor, maar natuurlijk ook je compiler (of interpreter), je favoriete browser en je lievelings besturingssysteem. Maar de (beginnende) programmeur heeft nog een vriendje. Deze vriend heet “array”. De array is een enorm handig verschijnsel dat je zal helpen bij vele problemen die je anders moeilijk op kan lossen.
Neem bijvoorbeeld een programma dat veertig verschillende getallen bij elkaar moet optellen. Het zou een beetje een heel erg gedoe zijn om nu allemaal variabelen met namen als a0, a1 tot en met a39 te gaan declareren. In de praktijk is dit niet te doen en je programma moet meteen weer volledig aangepast worden wil je 50, 60 of zelfs 1000 getallen bij elkaar optellen. Niet te doen dus. Daarvoor bestaat de array. Een array is niets meer dan een verzameling datatypen die een gezamenlijke “identifier” hebben.
Bij de meeste programmeertalen is een array gebonden aan een bepaald type (dus een array van het type float of van het type char), maar aangezien Python dynamisch getypeerd is hoef je daar geen rekening mee te houden. Een array kan dus tegelijkertijd integers en strings bevatten.
Om toch onderscheid te kunnen maken tussen de verschillende elementen van een array wordt er een “index” gebruikt. Dit is niets meer dan een geheel, positief getal (beginnend bij 0) waarmee een bepaald element in de array wordt aangeduidt.

>>> t = []
>>> print t
[]
>>> t = [4, 1, 9]
>>> print t
[4, 1, 9]
>>> print t[0], t[1], t[2]
4 1 9

Allereerst declareren we een lege array t. Zoals te zien is wordt een Array in Python met blokhaken aangegeven. Daarna maken we een een array aan met 3 elementen (4, 1 en 9). Zoals te zien is wordt de eerste keer de volledige array geprint terwijl bij het tweede print-statement alle elementen (met een index van 0 tot 2) afzonderlijk worden geprint.
Het mooie van Python is dat de grootte van arrays ook dynamisch is. Bij andere talen declareert de programmeur vaak een array van een bepaalde grootte waardoor er niet meer dan een bepaald aantal elementen in de array gestopt kan worden. Bij Python gaat dit allemaal veel makkelijker.

>>> t.append(6)
>>> print t
[4, 1, 9, 6]
>>> t[2] = 11
>>> print t
[4, 1, 11, 6]

Met de notatie .append() wordt er een element toegevoegd aan de array. Deze notatie volgt uit het Object-geOrienteerde Programmeren en dat zal in dit document niet behandelt worden. Het is voor jullie genoeg om te weten dat er simpelweg iets meegegeven kan worden aan de .append() call om iets toe te voegen aan de array.
De waardes van de dingen in de array kunnen simpelweg worden verandert op dezelfde manier zoals de waarde van een normale variabele wordt verandert. Let wel altijd op het index teken. Dit is voor beginners vaak een bron van verwarring. Elke, zichzelfrespecterende programmeertaal begint bij alles met tellen bij 0 en zo Python dus ook. Bij t[2] wordt dan ook het derde element in de array bedoeld, zoals ook te zien is aangezien de 9 dan in een 11 is veranderd.

>>> t.pop()
6
>>> print t
[4, 1, 11]
>>> t.pop(1)
1
>>> print t
[4, 11]

Met .pop() kunnen er elementen uit de array verwijdert worden. Standaard verwijdert pop() het laatste element en retouneert dat ook (waarom het ook op de standaard uitvoer wordt geprint). Er kan echter ook een index meegegeven worden zodat het element met die specifieke index uit de array wordt verwijderd. [3]

- Afsluiting

Ik hoop dat je nu wat meer duidelijk is over de edele kunst van het programmeren. Let wel, dit was echter een introductie tot de schamele basis van het programmeren. Bovendien is er nog niets verteld over het Object Georienteerde Programmeren. Dit is haast onmisbaar om volledig met de (uitgebreide) Python Bibliotheken te kunnen werken, maar ik vond het niet geschikt om meteen daarover al te beginnen. Een vervolg document zou misschien dus wel een goed idee zijn :).
Voor verdere vragen kan je altijd contact met mij opnemen via email of IRC, of ze stellen op het Mostly-Harmless forum [4]. Suggesties en andere op- of aanmerkingen zijn ook van harte welkom.

Vincent “gorny” Berg

- Literatuur

[1] Why Python? — Eric S. Raymond
http://www.linuxjournal.com/article.php?sid=3882

[2] Officiele Python Website
http://www.python.org

[3] Arrays in Python
http://users.ox.ac.uk/~sann1276/python/handbook/node39.html

[4] Mostly-Harmless Forums
http://www.mostly-harmless.nl/forums/

* EOF *


written by Remko

Leave a Reply