Geen stijlvol programma: Complexe datastructuren Arrays vijf verschillende variabelen voor iets dat als één rij getallen bestempeld wordt; onbruikbaar wanneer het over meer getallen (bijvoorbeeld ) gaat. = samenvoegen van gerelateerde variabelen van hetzelfde data-type Een lijst: een samengesteld data-type; een rij waarvan de elementen allemaal met dezelfde naam maar elk met een eigen volgnummer worden aangeduid; elementen hebben elk een eigen type, bijv. een geheel getal, een reëel getal maar ook een lijst. Waarom arrays Schrijf een programma dat gehele getallen leest en in omgekeerde volgorde terug afdrukt. # keerom.py: vijf getallen inlezen en in omgekeerde volgorde afdrukken Geef v i j f getallen a = int ( raw input ( getal : )) b = int ( raw input ( getal : )) c = int ( raw input ( getal : )) d = int ( raw input ( getal : )) e = int ( raw input ( getal : )) e, d, c, b, a #startoproep Creatie van een lijst: de verschillende elementen opsommen en omsluiten door vierkante haakjes: k = [,,,,, 6, 7] x = [.,.,.] a = [ [,], [,], [,6] ] l = [ ] # geneste lijst # lege lijst Individele elementen in de lijst: aanspreken via een index: een geheel getal, waarbij het eerste element vd. lijst index heeft Index groter of gelijk aan het aantal elementen in de lijst: foutmelding. Met een negatieve index: er wordt van achter naar voor geteld. x x [ ] #. k [ ], k[ ] # 7 # volledige lijst a [ ], a [ ] [ ] # [,] Een lijst opbouwen op basis van invoerwaarden of berekeningen: een element achteraan aan een lijst toevoegen met de append methode
# keerom.py: vijf getallen inlezen en in omgekeerde volgorde afdrukken AANTAL = l i j s t = [ ] Geef, AANTAL, v i j f getallen : for i in range (AANTAL) : invoer = raw input ( str ( i )+ : ) l i j s t. append ( int ( invoer ) ) i = AANTAL while i >= : l i j s t [ i ], i = # startoproep lijst i - 8 6 Input: 8 6 Output: 6 8 Numeric Python Alternatief voor het afdrukken in omgekeerde volgorde: for i in range (,AANTAL+) : l i j s t [ i ], raw input( str(i) + : ) functie str: zet getal (argument) om in een string. Aan deze string wordt een tweede string aangeplakt met de + operator. Het geheel wordt dan als prompt uitgeschreven door de raw_input functie. Technisch-wetenschappelijke toepassingen: rekenen met vectoren en matrices: lijsten van gerelateerde waarden van hetzelfde type (geheel,reëel,complex) list type van Python: maar een aantal veelvoorkomende operaties op vectoren en matrices vragen veel ruimte en tijd wanneer deze gedaan worden met de standaard datastructuren zoals lijsten. Oplossing: Numeric Python (NumPy) uitbreiding, een module met een heleboel gereedschappen om verzamelingen van objecten georganiseerd in roosterachtige schema s, zoals vectoren en matrices, efficiënt te manipuleren. (vrij gelijkaardig aan de werking van matrix-talen zoals APL en MATLAB) In de volgende subsecties worden een aantal elementen uit de NumPy module gebruikt om manipulaties op een- en twee-dimensionale arrays te doen. Hierbij worden niet alle specifieke mogelijkheden gebruikt, maar worden de bewerkingen geprogrammeerd op een manier vergelijkbaar met andere programmeertalen, zoals C, Java,...
Een-dimensionale arrays Een array is een object data-type: een rij waarvan de elementen allemaal met dezelfde naam maar elk met een eigen volgnummer worden aangeduid: alle elementen zijn van hetzelfde data-type en niet-leeg (vector) elk element in de array wijzigbaar gedurende de levensduur van de array lengte van een array: het aantal elementen, niet wijzigbaar: geen elementen toegevoegen aan of verwijderen uit de array Creatie: de array() functie: { eerste argument: list of tuple van waarden eventueel tweede argument: type van de elementen y = array((-.,.,.,.), float) Aantal in lijst lengte array # tuple Indien dit argument niet gegeven is, bepaalt Python zelf het type. type grootte van element (itemsize). In een array-element a[i] : i de index of subscript. Deze index kan een constante, een variabele of een expressie zijn. De waarde van de index moet wel een geheel getal zijn, groter of gelijk aan nul en kleiner dan het aantal elementen in de array. De waarde van de index kan ook negatief zijn, waarbij de absolute waarde van de kleinste negatieve waarde gelijk moet zijn aan het aantal elementen in de array. Bij een negatieve index wordt van achteraan in de array geteld. Technieken om een vector van een bepaalde lengte te creëren: vector met gehele getallen: met een variante van de range functie; vector met alle elementen gelijk aan : zeros waarbij het eerste argument met behulp van een lijst de lengte aangeeft en het tweede argument het type; vector met alle elementen gelijk aan : ones waarbij het eerste argument met behulp van een lijst de lengte aangeeft en het tweede argument het type. >>> x = array ([,, ]) # list >>> x array ([,, ]) >>> x [ ] >>> y = array ((.,.,.,.), f l oat ) # tuple >>> y [.... ] >>> y. s i ze >>> y. itemsize 8 verschillende elementen in array met index [] operator: >>> z = arange () >>> z [ 6 7 8 9] >>> z [ ], z [ ] 8 >>> nul = zeros ( [ 7 ], int ) >>> nul [ ] >>> een = ones ( [ 6 ], f l oat ) >>> een [...... ] y[], y[], y[], y[] lengte van de array is geen element y[]
Een array is een object: toekenning is het geven van een naam aan dat object. De naam is een aanduiding van of een referentie naar het object. Dmv. toekenningsstatement: naam copiëren naar een tweede naam: alias voor hetzelfde object, deze naam refereert naar datzelfde object. Wanneer een element in het object gewijzigd wordt door gebruik te maken van de eerste naam, dan zal deze wijziging ook te zien zijn, wanneer het object aangesproken wordt door de tweede naam. >>> a = array ( [.,.,. ] ) >>> b = a >>> b [ ] +=. >>> a=, a, b=, b a= [. 6.. ] b= [. 6.. ] # arsom. py: optellen van twee arrays from numpy import array, zeros a = array ( [.,.,.,.,. ] ) b = array ( [.,.,.,.,. ] ) c. c = zeros ( [ ], f loat ). 6... for i in range ( len (a )) : c [ i ] = a [ i ] + b [ i ] a... -.. a, +, b, >, c b..... # startoproep i Optellen van twee arrays De naam van de array zelf niet zomaar in om het even welke expressie geen aanduiding van een enkelvoudige geheugenplaats maar een referentie naar een object (aantal geheugenplaatsen). Rekenkundige operator + : optellen van de inhoud van twee geheugenplaatsen Toekenningsstatement (=): resultaat (object) een naam geven double a, b, c ; a b 9. =. + a = b + c ; object waarde c 6.6 waarde a, b en c : arrays deze rekenkundige operatie voorlopig NIET gebruiken: de optelling moet element per element gebeuren: Vergelijken van twee arrays De expressie a == b syntactisch wel correct semantisch anders geïnterpreteerd dan waarschijnlijk bedoeld is. Deze expressie gaat NIET na of de twee arrays dezelfde elementen bevatten. De gelijkheid nagaan moet weer element per element gebeuren in een lus. Na de lus kan de variabele gelijk getest worden. Wanneer deze gelijk is aan True, zijn de twee arrays gelijk (de waarden in de corresponderende elementen zijn gelijk).
# arvgl.py: vergelijken van twee arrays from numpy import array a = array ( [.,.,.,.,. ] ) b = array ( [.,.,.,.,. ] ) g e l i j k = True a for i in range ( len (a )) : if a [ i ]!= b [ i ] : b g e l i j k = False break a [ i ], b [ i ] i... -....... gelijk TrueFalse if g e l i j k : de twee arrays bevatten dezelfde waardes else : de twee arrays zijn verschillend kortsluitingsprincipe # startoproep # param.py : het gedrag van parameters import numpy def kwadar(x, y, n) : x = x x y [ i ] = y [ i ] y [ i ] return x n = a = b = numpy. zeros ( [ n ], int ) b [ i ] = i Voor oproep van de functie, a Functies met arrays als argumenten Bij oproep van functie met parameters: waarden van de actuele argumenten doorgeven naar de formele parameters: waarden van argumenten worden gebruikt als initialisatie voor parameters. In de functie zelf: formele parameters gebruikt als operands in expressies. Deze formele parameters kunnen daarbij van waarde veranderen. Wanneer functie uitgevoerd is en verlaten wordt (via return), deze eventuele aangepaste waarden van de formele parameters worden NIET teruggecopieerd naar de actuele argumenten in de oproep. en de r i j b bevat :, b [ i ], res = kwadar(a, b, n) Na oproep van de functie, a, met resultaat, res en de r i j b bevat :, b [ i ], # startoproep
syst i n a res main Voor oproep van de functie en de rij b bevat : 6 7 8 9 b 6 7 8 9 6 7 8 9 9 6 6 9 6 8 b kwadar x y i res Na oproep van de functie met resultaat en de rij b bevat : 9 6 6 9 6 8 Opgave. Een rij getallen in omgekeerde volgorde uitschrijven met behulp van functies. # keerom.py: getallen inlezen en in omgekeerde vo import numpy def l e e s r i j (x,m) : Geef een aantal gehele getallen for i in range (m) : invoer = raw input ( str ( i )+ : ) x [ i ] = int ( invoer ) def drukrij ( r,m) : for i in range (m) : r [m i ], invoer = raw input ( Geef aantal : ) m = int ( invoer ) a = numpy. zeros ( [m], int ) l e e s r i j (a,m) drukrij (a,m) # startoproep De waarde van a wordt doorgegeven naar de formele parameter x. In de functie kwadar wordt deze x gewijzigd. Maar na terugkeer in het hoofdprogramma is a niet gewijzigd. Dit niet geldt voor de array b: een array is een list, één van de basisobjecttypes van Python. Naam van zo n object: een aanduiding van of referentie naar dit object. syst m main 6 a 89 7 6 a Zo n naam als actueel argument doorgeven naar een formele parameter: de volledige array wordt NIET gecopieerd, maar de formele parameter wordt een tweede naam (alias, een bijkomende referentie) naar datzelfde object, net zoals bij een toekenning. a 7 89 leesrij x m drukrij r m In de functie kwadar: de formele parameter y refereert naar dezelfde array als het argument b in de oproep. Omdat de formele parameter refereert naar de originele rij, zal elke wijziging die in de functie door middel van de formele parameter gebeurt, uitgevoerd worden op deze originele rij. 99 levensduur bereik i i levensduur bereik
Meer-dimensionale arrays In veel toepassingen: een tabel of een matrix In Python: een lijst, waarbij elk element in deze lijst op zich een lijst is. Bij de definitie van de variabele kan deze geïnitialiseerd worden: a = [ [, ], [, ], [, ] ] >>> a = [ [,], [,], [,] ] >>> a [ [, ], [, ], [, ]] >>> a [ ] [, ] >>> a [ ] [ ] Met MAXRIJ gelijk aan en MAXKOLOM gelijk aan : a[][] a[][] a[][] a[][] a[][] a[][] eerste index : de rij tweede index de kolom in deze rij In het werkgeheugen: één lange rij van opeenvolgende elementen: a[][] a[][] a[][] a[][] a[][] a[][] is een rij van elementen waarin elk element op zich een rij is Module numpy een aantal functies waarmee op een klassiek wetenschappelijk-technische manier met matrices kan gewerkt worden. import numpy a = numpy. ones ( [MAXRIJ,MAXKOLOM], int ) b = numpy. zeros ( [MAXRIJ,MAXKOLOM], f l oat ) c = numpy. identity () functie ones een matrix waarbij de elementen van het type zijn, gegeven door het tweede argument; deze elementen krijgen de waarde Het eerste argument geeft aan hoeveel rijen (eerste getal in de lijst) en hoeveel kolommen (tweede getal in de lijst) er zijn. functie zeros : (gelijkaardig) een matrix, met elementen geïnitialiseerd op functie identity : vierkante identiteitsmatrix waavan de elementen van type float zijn Construeer een matrix waarin elk element gelijk is aan de som van de rij-index en de kolom-index en druk deze matrix af. # matrix.py: matrix met mat[i][j] = i+j import numpy MAXRIJ = MAXKOLOM = def drukmat(x,m, n) : for i in range (m) : for j in range (n) : %d % (x [ i ] [ j ] ), a = numpy. zeros ( [MAXRIJ,MAXKOLOM], int ) for r i j in range (MAXRIJ) :
De geconstrueerde matrix heeft volgende inhoud: for kolom in range (MAXKOLOM) : a [ r i j ] [ kolom ] = r i j + kolom drukmat( a,maxrij,maxkolom) #startoproep 6 en wordt in het werkgeheugen als één lange rij gestockeerd: 6 Bij oproep: actueel argument is een referentie naar een object In de formele parameter: een alias van deze referentie: duidt dus hetzelfde object aan. Dus eventuele wijzigingen in de matrix via de formele parameter: zichtbaar in het blok dat de functie opgeroepen heeft met de matrix als actueel argument. syst rij main kolom a 6 a drukmat x m n i Priemgetallen Opgave. Schrijf een programma met functies dat met behulp van de zeef van Eratosthenes alle priemgetallen kleiner dan afdrukt (alle niet-priemgetallen worden weggezeefd). vul zeef; doorloop zeef indien volgend element verschillend is van dit element is een priemgetal; schrap alle volgende veelvouden van dit element; j
index 6 7 8 9 6 7 8 zeef i = i = Programma met functies: Driehoek van Pascal e functie: n inlezen, e functie: de driehoek maken e functie: de driehoek afdrukken. i = i = i = 6 i = 7 i = i = i = 7 # zeef.py zoeken van priemgetallen ( Erathostenes) from numpy import def schrap ( zeef, p, n) : i = p while i <n : zeef [ i ] = i += p invoer = raw input ( Geef maximum voor priemgetallen : ) n = int ( invoer ) zeef = ones ( [ n ], int ) zeef [ ] = zeef [ ] = for i in range (,n) : if zeef [ i ] == : i schrap ( zeef, i, n) #startoproep (a + b) = (a + b) = a + b (a + b) = a + ab + b (a + b) = a + a b + ab + b ( ) n + = k ( ) ( ) n n + k k (a + b) = a + a b + 6a b + ab + b (a + b) n = ( ) n a n b + ( ) n a n b + ( ) n a n b +... + ( ) n n a b n + ( ) n n a b n # pascal.py: genereren van driehoek van Pascal import numpy MAX = def leesdimensie () : while True : invoer = raw input ( Geef dimenstie [.. +str (MAX)+ ] : ) n = int ( invoer ) return n if n < MAX : break
i- def maakdriehoek (a, n) : for i in range (,n+) : a [ i ] [ ] = a [ i ] [ i ] = for i in range (,n+) : for j in range (, i ) : j- j... a [ i ] [ j ] = a [ i ][ j ] + a [ i ][ j ]... ( ) i j = ( ) i + j ( ) i j Het resultaat voor n = 6: : : : : : 6 : 6: 6 6 i...... def driehoek (a, n) : for i in range ( n+) : %d % ( i ), :, for j in range ( i +) : %d % (a [ i ] [ j ] ), def : n = leesdimensie () a = numpy. zeros ( [ n+,n+], int ) maakdriehoek (a, n) driehoek (a, n) #hoofdprogramma Matrix-product Inlezen van twee matrices, product berekenen en resultaat afdrukken. c a b r r k ar ar ak = ak ak k l c rk = a rj b jk met l = ak j= ar
# matprod.py matrixproduct C = A x B import numpy MAX = def leesdimensie ( tekst ) : while True : invoer = raw input ( tekst ) n = int ( invoer ) if n < MAX : break return n def inwendigproduct (a, b, r, k, l ) : som =. for j in range ( l ) : som += a [ r ] [ j ] b [ j ] [ k ] invoer = input ( element +str ( i )+, +str ( j)+ : ) x [ i ] [ j ] = f l oat ( invoer ) ar = leesdimensie ( aantal r i j en van eerste matrix ) ak = leesdimensie ( aantal kolommen van eerste matrix ) a = numpy. zeros ( [ ar, ak ], f l oat ) leesmatrix (a, ar, ak) ak = leesdimensie ( aantal kolommen van tweede matrix ) b = numpy. zeros ( [ ak, ak ], f l oat ) leesmatrix (b, ak, ak) c = numpy. zeros ( [ ar, ak ], f l oat ) maakproduct(a, b, c, ar, ak, ak) matrix (a, ar, ak ) matrix (b, ak, ak ) matrix (c, ar, ak ) return som def maakproduct(a, b, c, ar, ak, ak) : for r in range ( ar ) : for k in range ( ak) : c [ r ] [ k ] = inwendigproduct (a, b, r, k, ak ) def matrix (x,m, n) : for i in range (m) : for j in range (n) : %9. f % (x [ i ] [ j ] ), # startoproep def leesmatrix(x,m, n) : for i in range (m) : for j in range (n) :
Begrippen Array: declaratie en initialisatie. De selectie-operator []. Een arraynaam als argument bij een functieoproep. Meer-dimensionale arrays. def rechtsonder (a, n) : %d % ( i ), :, for j in range ( n i ) :, for j in range ( n i,n) : %d % (a [ i ] [ j ] ), 6 6 7 6 7 8 6 7 8 9 6 7 8 9 def linksboven (a, n) : Driehoeksgedeelten van een matrix %d % ( i ), :, for j in range (n i ) : %d % (a [ i ] [ j ] ), def rechtsboven (a, n) : %d % ( i ), :, for j in range ( i ) :, for j in range ( i, n) : %d % (a [ i ] [ j ] ), 6 6 7 6 7 8 8 9