#ubuntu-nl-mwanzo-klas 2011-03-12
<leoquant> het staat hier nu op +m commandoline  en StefandeVries
<leoquant> ik ga zo eten, maar op de tijd terug te zijn hier
<StefandeVries> dank je, leoquant
<StefandeVries> tot later
<leoquant> alvast weer bedankt, en succes
<commandoline> Welkom bij de zesde les Python allemaal
<commandoline> we gaan vandaag verder met functies
<commandoline> maar voordat we dat doen wil ik even het huiswerk bespreken
<commandoline> ten eerste de opdracht om een eigen alternatief voor de len()-functie te schrijven.
<commandoline> genaamd num()
<commandoline> http://paste.ubuntu.com/579208/
<commandoline> goed, even lijn voor lijn wat er gebeurd.
<commandoline> we beginnen met het definiÃ«ren van de functie num(), zodat we die later kunnen gebruiken. De functie heeft Ã©Ã©n argument, items, wat de list/dictionary is waarvan we de lengte willen weten.
<commandoline> daarna volgt de code om de eigenlijke lengte te berekenen:
<commandoline> de code loopt met behulp van de for-loop door alle items, en hoogt voor ieder item de teller 'aantal' op met 1.
<leoquant> hannie> Het werkt bij mij ook zonder argument
<commandoline> ten slotte wordt aantal teruggegeven aan de aanroeper
<commandoline> terwijl StefandeVries hannie's vraag beantwoord, leg ik nog even de laatste paar regels uit
<commandoline> daar wordt de functie nl. gebruikt.
<commandoline> <StefandeVries> hannie: het kan zijn dat dat toevallig goed ging, maar voor een goede programmeerstijl vooral erin houden
<commandoline> was het antwoord.
<commandoline> om de functie te testen maken we twee dingen (objecten) aan: een list en een dictionary
<commandoline> over beide wordt zowel de functie num() als len() aangeroepen, en beide geven hetzelfde resultaat terug.
<commandoline> overigens: de functie len() is intern anders geimplementeerd, en kan meer. Gebruik dus nooit een eigen implementatie in de praktijk, nergens voor nodig ;)
<commandoline> goed, begrijpt iedereen wat er hier gebeurd?
<commandoline> geen vragen? Dan gaan we verder naar de tweede opdracht
<commandoline> http://paste.ubuntu.com/579219/
<commandoline> wat we hier zien is het bekende rekenmachineprogramma, maar weer in een andere vorm.
<commandoline> als je wat anders hebt hier is het niet vreemd, want het kan op verschillende manieren
<commandoline> maar wat wij kortweg gedaan hebben:
<commandoline> maar wat wij kortweg gedaan hebben:
<commandoline> :(
<commandoline> - een functie maken voor het menu, zoals we die dacht ik vorige les al hadden gezien.
<commandoline> - ieder menuitem in een functie gezet, om de code wat duidelijker te houden.
<commandoline> wat nog had gekunt was het vragen van getallen in een functie zetten, of het verplaatsen naar voor het if-statement
<commandoline> (if keuze == 1; if keuze == 2 etc.)
<commandoline> maar zoals ik al zei, er zijn hier meerdere mogelijkheden
<commandoline> ok, nog vragen?
<commandoline> goed, dan gaan we verder
<commandoline> jullie weten nu hoe je zelf functies kan schrijven, en hoe je ze aanroept.
<commandoline> <CasW> Waarom geen switch-case?
<StefandeVries> Die bestaat niet in Python
<commandoline> er is overigens wel een mogelijkheid:
<commandoline> een dictionary maken met functies daarin
<commandoline> maar dat is hier denk ik alleen maar onduidelijker
<leoquant> CasW> Waarom geen switch-case?
<commandoline> het mooie aan python is, dat de makers ervan al een heleboel functies hebben geschreven die wij kunnen gebruiken in onze programma's met maar weinig moeite
<commandoline> leoquant, die vraag is net beantwoord ;)
<leoquant> !
<commandoline> en vandaag wilde ik jullie dus een aantal van die functies laten zien
<commandoline> allemaal gaat niet lukken, want het zijn er honderden
<commandoline> maar ik zal er een aantal laten zien die ik en StefandeVries vaak gebruiken
<commandoline> open allemaal een terminal met daarin python
<commandoline> dit is makkelijker om uit te proberen in de interactieve sessie dan in een opgeslagen programma.
<commandoline> dus:
<commandoline> Toepassingen > Hulpmiddelen > Terminalvenster
<commandoline> 'python' intikken en op enter drukken
<commandoline> goed, omdat python zoveel functies ingebouwd heeft, zijn ze geordend in zogenaamde 'modules'.
<commandoline> standaard zijn modules niet geladen, dat moeten we doen op het moment dat we ze willen gebruiken.
<commandoline> De eerste module die ik jullie wil laten zien, is de os module
<commandoline> die kun je laden door 'import os' in te tikken.
<commandoline> overigens staat de uitgebreide (Engelstalige) documentatie van alle modules hier: http://docs.python.org/library/
<commandoline> en van de os-module specifiek: http://docs.python.org/library/os.html
<commandoline> goed, de eerste functie die ik wil bespreken is os.listdir()
<commandoline> die heeft Ã©Ã©n argument, zoals ook hier te lezen valt: http://docs.python.org/library/os.html#os.listdir
<commandoline> nl. een locatie
<commandoline> de functie geeft na aanroepen een lijst terug met alle bestanden en mappen in 'locatie'
<commandoline> type in:
<commandoline> os.listdir(".")
<commandoline> . is de huidige map, dat is in de meeste gevallen jullie home-map.
<commandoline> je ziet trouwens ook alle verborgen bestanden, dus het kan nogal een lange lijst teruggeven.
<commandoline> je kan ook een andere locatie ("path") proberen
<commandoline> bijv.:
<commandoline> os.listdir("/home")
<commandoline> ok, volgende functie:
<commandoline> os.remove()
<commandoline> daarmee moet je oppassen
<commandoline> het verwijdert nl. een bestand, en dat zonder te vragen of je het zeker weet o.i.d.
<commandoline> je kan 'm uitproberen door een lege map aan te maken met daarin een leeg bestand
<commandoline> <hannie> moet je bij elke terminalsessie opnieuw importeren?
<commandoline> <CasW> Ja
<commandoline> en dan dat bestand verwijderen
<commandoline> het argument werkt net zoals bij os.listdir
<commandoline> maar doe dat alleen als je bovenstaande instructies begrijpt.
<commandoline> overigens kan je os.remove niet gebruiken om mappen weg te gooien
<commandoline> alleen bestanden, en dan Ã©Ã©n voor Ã©Ã©n.
<commandoline> voor mappen kun je os.rmdir gebruiken
<commandoline> maar die werkt alleen als de map die je probeert te verwijderen compleet leeg is
<commandoline> dan is er nog Ã©Ã©n functie uit os die ik jullie wil laten zien: os.walk()
<commandoline> <MedUsaXIII> Vraag: Dus je gebruikt os.remove in combinatie met os.rmdir om een map met bestanden weg te gooien >?
<commandoline> dat kan, zeker als je 'm combineert met os.walk die we nu bespreken zoals je straks misschien zult zien.
<commandoline> maar makkelijker is om de shutil module te gebruiken.
<commandoline> die heeft functies als rmtree()
<commandoline> dat alles in een map verwijdert, dat zijn dus de echt gevaarlijke functies als je niet precies weet waar je mee bezig bent
 * commandoline heeft er een keer m'n halve home map mee leeggegooid.
<commandoline> *z'n, als ik /me gebruik :P
<commandoline> ok, os.walk:
<commandoline> http://docs.python.org/library/os.html#os.walk
<commandoline> die functie wordt meestal gebruikt i.c.m. de for-loop
<commandoline> ik zal een voorbeeldje ervan geven, maar het verder niet uitleggen.
<commandoline> als het nu niet duidelijk is, komt dat vanzelf.
<commandoline> http://paste.ubuntu.com/579427/
<commandoline> je kan het overtypen in de terminal, maar als jullie syntax errors krijgen zet het dan gewoon even in een bestand
<commandoline> <FOAD> En niet met "marten" zeker.
<commandoline> even aanpassen idd
<StefandeVries> Tenzij je Marten heet
<commandoline> idd :P
<commandoline> goed, tenzij iemand nog vragen heeft over os wil ik door met os.path
<StefandeVries> Ik zie geen vragen =)
<commandoline> os.path is een zogenaamde submodule van os
<commandoline> en dat heeft als voordeel dat je 'm niet hoeft te importeren als je os al hebt geimporteerd
<leoquant> <hannie> ik krijg geen output
<StefandeVries> hannie: staat er iets op je bureaublad, en heb je je gebruikersnaam aangepast?
<commandoline> als de map niet bestaat zou hij een foutmelding geven, en hij geeft altijd wat output.
<commandoline> het werkt hier gewoon, dus hier komen we later even op terug hannie
<commandoline> importeren
<commandoline> <hannie> na enter zie ik >>>
<commandoline> bedoel ik
<commandoline> lijkt me toch dat het bureaublad leeg is, maar goed, zo verder.
<commandoline> je kan os.path wel importeren via 'import os.path' overigens
<commandoline> als je dat doet is os.listdir niet beschikbaar
<commandoline> maar goed, jullie hebben os geimporteerd, dus automatisch ook os.path
<commandoline> dus, door naar de eerste functie
<commandoline> (nadat jullie de documentatie hebben gekregen van os.path: http://docs.python.org/library/os.path.html)
<commandoline> de eerste functie uit os.path die ik wil behandelen is os.path
<commandoline> stel je voor dat je weet dat je op linux werkt, en dat er een /home map bestaat.
<commandoline> en de gebruikersnaam niet weet
<commandoline> dan kun je die vragen aan de gebruiker
<commandoline> je zou dan iets kunnen doen als:
<commandoline> locatie = "/home/" + raw_input("Geef de gebruikersnaam: ")
<commandoline> het probleem aan deze code is dat zodra de / achter home weg gaat, de code crasht
<commandoline> voor dat soort problemen hebben de python ontwikkelaars de functie os.path.join() geschreven
<commandoline> die werkt op ieder platform waarop python draait
<commandoline> dus op linux, mac os x, windows, bsd, etc. etc.
<commandoline> de code uit mijn voorbeeld wordt er als volgt mee herschreven:
<commandoline> locatie = os.path.join("/home", raw_input("Geef de gebruikersnaam: "))
<commandoline> <hannie> als je de gebruikersnaam niet weet kan je hem ook niet intypen
<commandoline> <CasW> Je == de programmeur, voor als je een programma voor iemand anders schrijft
<commandoline> ok, iedereen begrijpt de werking van os.path.join() ?
<commandoline> de volgende is os.path.splitext()
<commandoline> die kan je bijv. gebruiken als je een programma hebt dat bestanden maakt met de extensie .jdkf
<commandoline> om een voorbeeld te noemen :P
<commandoline> je wil dan contoleren of het bestand wat de gebruiker selecteert, eindigt op 'jdkf'
<commandoline> dat kan op verschillende manieren, maar Ã©Ã©n daarvan is om de extensie op te vragen met os.path.splitext()
<commandoline> het voorbeeld zou je bijv. kunnen vertalen naar de volgende code:
<commandoline> if os.path.splitext("/locatie/die/eindigt/op.jdkf")[1] == "jdkf":
<commandoline> #alles goed
<commandoline> <hannie> hiermee worden dus de naam en de extensie gescheiden
<commandoline> inderdaad, er wordt een 'tuple' (een soort list) teruggegeven.
<commandoline> met twee items:
<commandoline> alles wat voor de extensie staat
<commandoline> en de extensie
<commandoline> met [1] krijg ik dus de extensie
<commandoline> met [0] krijg ik alles wat daarvoor staat.
<commandoline> ok, dat was alles wat ik wilde laten zien van os.path
<commandoline> iemand nog vragen tot zover?
<commandoline> nee, dan pakken we de volgende module erbij:
<commandoline> math
<commandoline> dus, doe allemaal:
<commandoline> import math
<commandoline> math bevat wiskundige functies, zoals sqrt (square root = vierkantswortel)
<commandoline> je kan er dus de wortel mee uit een getal trekken.
<commandoline> math.sqrt(2) geeft bijv.
<commandoline> 1.4142135623730951
<commandoline> en zo zitten er nog veel meer functies in.
<commandoline> kijk gewoon de documentatie eens door als je ze nodig hebt:
<commandoline> http://docs.python.org/library/math.html
<commandoline> ok, ik heb nog twee modules, en omdat het idee zolangzamerhand wel duidelijk is, wil ik daar wat sneller doorheen
<commandoline> we willen niet over de tijd heengaan...
<commandoline> de eerste is subprocess
<commandoline> import subprocess
<commandoline> dus
<commandoline> subprocess maakt het mogelijk om andere applicaties te starten
<commandoline> probeer bijv. eens:
<commandoline> subprocess.call(["firefox"])
<commandoline> of: subprocess.call(["python", "bestand_om_uit_te_voeren.py"])
<commandoline> <FOAD> Waarom die haakjes?
<StefandeVries> FOAD: de ronde haakjes omdat het een functieaanroep is
<StefandeVries> FOAD: de vierkante omdat elk argument een element van een lijst is
<commandoline> en die functie vraagt nou eenmaal een lijst als invoer
<StefandeVries> Helder?
<StefandeVries> Mooi
<commandoline> ok, het is mogelijk om i.p.v. subprocess.call os.system te gebruiken. De python handleiding zegt niet dat die laatste veroudert is, maar dat wordt door sommige mensen wel zo gezien.
<commandoline> dus mijn persoonlijke advies is om gewoon de subprocess module te gebruiken om commando's uit te voeren als dat al moet
<commandoline> want, door dit soort commando's uit te voeren, maak je je programma systeemafhankelijk
<commandoline> sommige van deze commando's zouden mogelijk bijv. niet werken op windows.
<commandoline> ok, dan de laatste module nog even snel: sys
<commandoline> doe:
<commandoline> import sys
<commandoline> en vervolgens:
<commandoline> sys.exit()
<commandoline> en python is afgesloten
<commandoline> je hebt ook de exit() functie hiervoor, maar die werkt in sommige gevallen niet
<commandoline> (bijv. bij jython, even googlen als je nieuwsgierig bent daarnaar.)
<commandoline> ook is het mogelijk om via sys argumenten mee te krijgen:
<commandoline> bijv. als je programma zo wordt aangeroepen:
<leoquant> <hannie> waarom niet quit()
<commandoline> python programma.py argument1 argument2
<commandoline> dan kan je argument1 en argument2 zien via de list 'sys.argv'
<commandoline> probeer het maar eens uit
<StefandeVries> hannie: bij sommige Pythons werkt dit niet. sys.exit() werkt altijd en is veiliger
<commandoline> en het is ook een keuze van de python ontwikkelaars geweest om het exit() te noemen :)
<commandoline> ok, nog even huiswerk:
<commandoline> schrijf een programma, dat de gebruiker om een map vraagt
<commandoline> en vervolgens alle python programma's in die map uitvoert.
<leoquant> leuk
<commandoline> en dan hoop ik jullie volgende week allemaal weer te zien
<commandoline> StefandeVries en ik zijn hier nog even voor vragen :)
<StefandeVries> En dat hoop ik uiteraard ook ;)
<commandoline> en ook door de week mag je altijd vragen stellen in #ubuntu-nl-mwanzo of via PM's aan ons.
 * leoquant biedt virtuele bloemen aan de leiders
<leoquant> dit kanaal is weer open nu
