ID.nl logo
Zo kun je programmeren in Python - deel 8
© Reshift Digital
Zekerheid & gemak

Zo kun je programmeren in Python - deel 8

Tot nu toe leerde je heel wat mogelijkheden van de programmeertaal Python. Misschien ben je buiten onze lessen zelf al aan de slag gegaan met je kennis. Super, want programmeren leer je door het veel te doen. Maar een goed programma is ook gedocumenteerd en goed getest. Dat leer je in onze achtste les.

Hier vind je les 1 van de Python-cursus.

Verkeerde gewoontes leer je niet snel af, daarom dat we nu even een stapje terugdoen en nadenken over wat ‘goede code’ is. Na deze les kun je code produceren die niet alleen goed gedocumenteerd en goed getest is, maar weet je ook hoe je informatie over Python-modules opzoekt met de helpfunctie.

Code documenteren met commentaar

Tot nu toe schreven we onze code zonder enige vorm van documentatie. Als je met anderen samenwerkt aan een programma, is het belangrijk dat je die documenteert, zodat je anderen duidelijk maakt wat je met je code bedoelt. Maar ook als je helemaal alleen programmeert, is documentatie geen overbodige luxe. Zo begrijp je je eigen code nog als je er over een jaar opnieuw naar kijkt.

De eerste manier om je code te documenteren is met commentaar. Alles na het #-teken (hekje) tot het einde van de regel (behalve als het hekje ín een string voorkomt) is commentaar en wordt door Python genegeerd. Op die manier kun je een uitleg voor jezelf of anderen schrijven. Als je bijvoorbeeld in de functie is_palindroom van deel 6 in de war raakt met die indexen, schrijf er dan gerust wat commentaar bij:

if letters[0] != letters[-1]: # Als de eerste en de laatste letter verschillen

Het getuigt van goede stijl om twee spaties tussen je code en het erna volgende commentaarteken te houden en één spatie tussen het commentaarteken en je commentaar. Overigens kun je ook commentaar op een nieuwe losstaande regel beginnen, dan spreken we van een commentaarregel:

# Als de eerste en de laatste letter verschillen

if letters[0] != letters[-1]:

Het is de gewoonte om een commentaarregel te zetten op de regel vóór de regel waarover hij gaat.

Code uitcommentariëren

Het commentaarteken (#) wordt ook weleens gebruikt om code die je aan het testen bent maar die niet blijkt te werken tijdelijk ‘uit te commentariëren’ ofwel uit te zetten. Door een commentaarteken voor de code te zetten, wordt de code door Python genegeerd, maar kun je hem erna wel eenvoudig weer inschakelen door het commentaarteken weg te halen. Op deze manier gebruik je het commentaarteken dus niet voor documentatie, maar eigenlijk als hulpmiddel bij het debuggen.

Code documenteren met docstrings

Commentaar gebruik je om te documenteren waarom je iets doet en hoe je het doet, maar voor gebruikers van je code is vooral belangrijk wat die doet. Om dat te documenteren, gebruik je docstrings: in het begin van elke module, elke klasse en elke functie of methode geef je met een string tussen drie dubbele aanhalingstekens aan wat het stuk code doet.

Zo zouden we onze klassen uit de vorige les als volgt kunnen documenteren:

"""Klassen om met tweedimensionale, driedimensionale en hogerdimensionale punten te werken."""

import math

class Point:
"""Stelt een punt voor in een willekeurig aantal dimensies."""

def __init__(self, *coordinates):
"""Initialiseer het punt met de opgegeven coördinaten."""
self.coordinates = list(coordinates)

def __repr__(self):
"""Geef een leesbare voorstelling van het punt terug."""
return 'Point(' + ', '.join(str(co) for co in self.coordinates) + ')'

def displacement(self, other_point):
"""Geef het verschil terug tussen dit punt en een ander punt.

De overeenkomstige coördinaten worden van elkaar afgetrokken.

Voorbeeld: het verschil tussen Point(1, 4, 2) en Point(3, 4, 1) is gelijk aan Point(2, 0, -1).
"""
return Point(*[a-b for a, b in zip(other_point.coordinates, self.coordinates)])

def distance(self, other_point):
"""Geef de Euclidische afstand terug tussen dit punt en een ander punt."""
relative_position = self.displacement(other_point)
return math.sqrt(sum(i**2 for i in relative_position.coordinates))
class Point2D(Point):
"""Stelt een tweedimensionaal punt voor."""

def __init__(self, x=0, y=0):
"""Initialiseer het punt met de opgegeven x- en y-coördinaten."""
Point.__init__(self, x, y)
self.x = x
self.y = y
def get_x(self):

"""De x-coördinaat van het punt."""
return self.coordinates[0]

def set_x(self, x):
self.coordinates[0] = x

x = property(get_x, set_x)

def get_y(self):
"""De y-coördinaat van het punt."""
return self.coordinates[1]

def set_y(self, y):
self.coordinates[1] = y

y = property(get_y, set_y)

Je ziet hier dat documentatie niet lang hoeft te zijn. De docstrings bij de module, de klassen en bij de meeste methodes zijn maar één regel lang.

De moeilijkste methode om te begrijpen is displacement en daarom is het zinvol om daar wat meer uitleg bij te geven. Bij een docstring van meer dan één regel raden we aan om na de eerste regel een lege regel te houden, en om de drie dubbele aanhalingstekens op het einde op een nieuwe regel te zetten. Dat geeft wat meer overzicht.

Merk op: bij onze eigenschappen x en y van de klasse Point2D documenteren we alleen de methode die de waarde van de eigenschap opvraagt. Zo toont de ingebouwde helpfunctie van Python (die we op het einde van deze les bespreken) deze documentatie bij de eigenschap.

Interactieve voorbeelden in docstrings

We hebben in de docstring van de methode displacement al een voorbeeld van het gebruik van de methode gegeven als documentatie. Maar dat bleef nogal informeel. We kunnen die documentatie ook in de vorm van echte Python-code doen die je in een interactieve terminalsessie zou kunnen invoeren. Zo kan de gebruiker die de documentatie leest, onmiddellijk de voorbeelden kopiëren uit de documentatie en plakken in de Python-interpreter om ze uit te proberen. Dat zou voor de methode displacement er dan als volgt uitzien:

def displacement(self, other_point):"""Geef het verschil terug tussen dit punt en een ander punt.

De overeenkomstige coördinaten worden van elkaar afgetrokken.

>>> Point(1, 4, 2).displacement(Point(3, 4, 1))Point(2, 0, -1)"""return Point(*[a-b for a, b in zip(other_point.coordinates, self.coordinates)])

Je ziet hier dat je de code na de >>> exact in een Python-terminalsessie zou kunnen invoeren en dan ook het resultaat zou krijgen dat hier staat. In feite hebben we wat hier staat gewoon eerst in de terminal van Thonny ingevoerd en dan samen met de uitvoer gekopieerd en hier in de docstring geplakt.

Code testen met doctest

Stel dat je nu ooit de code van de methode displacement aanpast omdat je denkt een verbetering te zien, maar er een fout in maakt, waardoor het resultaat verkeerd is. Dan kun je dat testen door de voorbeeldcode in je docstring uit te voeren in een Python-terminalsessie. Voer je de code uit en komt het resultaat niet overeen met de uitvoer in de docstring, dan klopt je code niet meer.

Maar zouden we die test niet automatisch kunnen doen? Jazeker! Python kent daarvoor de module doctest, die automatisch alle docstrings in een module kan testen op interactieve voorbeelden. Dat voer je als volgt uit in een Linux- of macOS-terminal of de Windows Opdrachtprompt:

python3 -m doctest -v point.py

Hierbij is point.py de naam van de module met je code erin. Je krijgt dan als uitvoer de tests die doctest in je docstrings ziet en het resultaat. Als je het alleen wilt zien als een test een fout vindt, haal dan de optie -v weg. Stel dat je bijvoorbeeld per ongeluk de * vergeten bent in de methode displacement om de lijst naar een willekeurig aantal argumenten voor de klasse Point om te zetten, dan zal doctest die fout opmerken met de volgende melding:

**********************************************************************

File "point.py", line 21, in point.Point.displacement

Failed example:

Point(1, 4, 2).displacement(Point(3, 4, 1))

Expected:

Point(2, 0, -1)

Got:

Point([2, 0, -1])

**********************************************************************

1 items had failures:

1 of

***Test Failed*** 1 failures.

Een goede manier van programmeren is dan ook dat je je code zoveel mogelijk documenteert met docstrings en daarin ook interactieve voorbeelden opneemt, die je na elke wijziging van je code automatisch test met doctest om je ervan te verzekeren dat je geen fouten hebt geïntroduceerd.

De helpfunctie gebruiken

Als je code is gedocumenteerd, hoef je niet je codebestand in Thonny te openen om de documentatie te bekijken. Je kunt dit in een interactieve Python-sessie, bijvoorbeeld in Thonny, maar ook in een Python-sessie in een Linux- of macOS-terminal of de Windows Opdrachtprompt. Het enige wat je hoeft te doen, is de functie help op te roepen met de naam van de module, klasse, functie of methode waarvoor je de documentatie wilt zien. Bijvoorbeeld in Thonny:

>>> help(Point.displacement)

Help on function displacement in module __main__:

displacement(self, other_point)

Geef het verschil terug tussen dit punt en een ander punt.

De overeenkomstige coördinaten worden van elkaar afgetrokken.

>>> Point(1, 4, 2).displacement(Point(3, 4, 1))

Point(2, 0, -1)

Overigens zijn alle standaardmodules van Python uitgebreid gedocumenteerd met docstrings. Daardoor kun je van alle modules, klassen, functies en methodes heel eenvoudig documentatie opvragen in je Python-terminalsessie. Let er wel op dat je een module eerst dient te importeren voordat je er documentatie van kunt opvragen met help.

Samenvatting

In deze les ging het minder over het programmeren zelf, maar over het documenteren en testen van je Python-programma’s en het uitzoeken van meer informatie over de standaard Python-modules of je eigen modules. Hoe complexer je programma’s zijn, hoe belangrijker dit soort zaken rond je code zijn. Maak er daarom een gewoonte van om documentatie en tests niet als een nabeschouwing te zien, maar al tijdens de ontwikkeling van je programma in je code te integreren. In de volgende les maken we het nog complexer: dan gaan we extra modules installeren die niet in Python ingebouwd zijn.

Opdracht 1

Voer de helpfunctie eens uit op je klasse Point2D. Wat zou er nog beter kunnen aan de getoonde documentatie?

Uitwerking opdracht 1

*>>> from point import Point2D

help(Point2D)* De helpfunctie van onze klasse toont niet alleen de eigenschappen x en y bij de Data descriptors, maar toont ook de methodes get_x, set_x, get_y en set_y. Dat is wat te veel van het goede. Die methodes hoeven niet getoond te worden. Daar doen we in de volgende opdracht iets aan.

Opdracht 2

We hebben een eigenschap zoals x in de klasse Point2D tot nu toe geconstrueerd met methodes get_x en set_x en een opdracht als x = property(get_x, set_x) om deze methodes samen als eigenschap te gebruiken. Maar je kunt een eigenschap ook met een decorator definiëren en dan worden die methodes niet in de helpuitvoer getoond. Zoek zelf met de ingebouwde helpfunctie van Python op hoe je dat doet.

Uitwerking opdracht 2

Met help(property) krijg je uitleg over de opdracht property. Je leert er zelfs dat het geen opdracht maar een klasse is. Het in de helpuitvoer getoonde voorbeeld kun je bijna rechtstreeks toepassen op onze klasse Point2D. Dan kom je tot de volgende code voor x: *@propertydef x(self):"""De x-coördinaat van het punt."""return self.coordinates[0]@x.setter**def x(self, x):*self.coordinates[0] = x Doe hetzelfde voor y. Voer de helpfunctie opnieuw uit op je klasse en verifieer dat je alleen nog maar hulp over de eigenschappen krijgt en niet meer over de methodes die de eigenschappen opbouwen.

Cheatsheet

Commentaar: een regel die begint met # en dient als uitleg bij een stukje code. Debuggen: fouten (bugs) in je code opsporen en verhelpen. Docstring: een string tussen drie dubbele aanhalingstekens die een module, klasse, functie of methode documenteert. Uitcommentariëren: een regel code uitschakelen door er een commentaarteken voor te zetten.

▼ Volgende artikel
Review Huawei Freeclip 2 – Voel je niet, hoor je wel
© Wesley Akkerman
Huis

Review Huawei Freeclip 2 – Voel je niet, hoor je wel

De Huawei Freeclip 2 is een opmerkelijke set oordopjes. Niet alleen omdat je ze om je oren draagt, alsof het oorbellen met clipjes zijn, maar omdat er een bijzonder verrassend geluid uit komt, ondanks dat compacte formaat. Het grootste minpunt? De prijs…

Goed
Conclusie

Met een prijskaartje van pakweg 200 euro moet je diep in de buidel tasten voor de Huawei Freeclip 2. Maar daar krijg je dan ook wel de meest comfortabele open-ear-oordoppen van dit moment voor terug. Koppel dat aan een warme en vertrouwde audiobeleving en je houdt een set over die in deze categorie zijn weerga niet kent. Het gedoe met de app en de bediening is vervelend, zeker op dit prijspunt, dus hopelijk doet de fabrikant daar nog iets mee.

Plus- en minpunten
  • Ongekend draagcomfort
  • Audio klinkt warm en vertrouwd
  • Overzichtelijke applicatie
  • Lekker compact oplaadhoesje
  • Lange batterijduur
  • Audio kan vervormd klinken na equalizer
  • Hoge aanschafprijs
  • Fysieke bediening wat onhandig
  • App met een omweg installeren
CategorieSpecificatie
AfmetingenOordopje: ca. 25,4 × 26,7 × 18,8 mm; Case: ca. 50 × 49,6 × 25 mm
GewichtEnkel oordopje: ca. 5,1 g; Oplaadcase: ca. 37,8 g
BouwIP57 (oordopjes), IP54 (oplaadcase)
ConnectiviteitBluetooth 6.0; Protocol: A2DP 1.3, HFP 1.7, AVRCP 1.6
Batterij60 mAh per oordopje, 537 mAh in de oplaadcase (Lithium-ionpolymeer)
GebruiksduurMuziek: 9 uur (oordopjes) / 38 uur (met case)
OpladenUSB Type-C, draadloos opladen, 40 min voor oordopjes (3C-laadtempo)
AudioDual-engine driver (10,8 mm), bereik 20 Hz tot 20.000 Hz
CodecsL2HC, AAC, SBC ondersteuning via A2DP
Microfoons4 MEMS-microfoons en 2 VPU-microfoons voor heldere gesprekken

Het kan zijn dat het ontwerp van de Huawei Freeclip 2 je nog niet bekend voorkomt. Toch bestaat dit soort oordopjes al een tijdje. Niet alleen in de vorm van de voorganger van dit model; Motorola heeft bijvoorbeeld de Buds Loop, terwijl JBL eerder de Soundgear Clips aankondigde. Desondanks geniet de productcategorie nog weinig populariteit. Waarschijnlijk vanwege de iets minder audiokwaliteit en iets hogere aanschafprijs in vergelijking met 'normale' oortjes.

De Huawei Freeclip 2 valt (net als zijn soortgenoten) onder de categorie open-ear-oordopjes (en subcategorie C-bridge). Dat betekent dat ze niet ín je oren gaan, maar net boven de gehoorgang hangen en de muziek als het ware de opening in blazen. Daardoor blijf je goed in contact met je directe omgeving terwijl je naar je eigen muziek luistert, en anderen hebben daar weinig last van: er lekt soms wat geluid weg, maar meestal zo zacht dat het nauwelijks stoort.

©Wesley Akkerman

Verbeteringen Huawei Freeclip 2

Mocht je al weg bekend zijn met de Huawei Freeclip, dan is het goed om even kort te verbeteringen te bespreken. Deze set beschikt bijvoorbeeld over adaptieve audio, waardoor hij het volumeniveau aan de omgevingsgeluiden kan aanpassen. Daarnaast kun je de hardware bedienen met zowel tik- als veegbewegingen. De batterijen houden het één uur langer vol (nu negen uur) en het oplaadhoesje gaat twee uur langer mee (nu in totaal 38 uur).

Ook mooi meegenomen: de oorhangers wegen ongeveer elf procent minder dan de eerste variant, terwijl Huawei niet inleverde op audiokwaliteit. Sterker nog: die is er op vooruitgegaan. Muziek klinkt over het algemeen helder en fris en als je binnen de bijbehorende app de equalizer gebruikt, ook nog eens warm en omhelzend. De bas kan soms wat scherp klinken en er treedt enige vervorming op na het gebruik van die equalizer, maar dit valt allemaal binnen de verwachting.

©Wesley Akkerman

De afweging maken

Je kunt van een set open-ear-dopjes namelijk niet dezelfde audiokwaliteit verwachten als van oordoppen die daadwerkelijk je gehoorgang ingaan en de boel netjes afsluiten. Desondanks zijn we onder de indruk van de audiokwaliteit. Je favoriete tunes klinken aangenaam en vertrouwd; een groter compliment kunnen we open-ear-setjes niet geven. Onze ervaringen met andere merken dopjes laten qua audio nog wel eens wat te wensen over, maar hier vallen veel negatieve ervaringen weg.

Zoals gezegd klinkt de audio niet perfect. Je mist soms wat detail en ook de bredere soundstage die je krijgt met oordoppen die je afsluiten van de wereld. De vraag is alleen: maakt dat in de praktijk veel uit? Meestal niet, want met open-ear-modellen kies je bewust voor die balans. Je levert iets in op geluidskwaliteit, maar je blijft je omgeving horen. Daardoor lenen dit soort sets zich perfect lenen voor bijvoorbeeld fietsers en wanneer je in de sportschool bent: momenten waarop je niet helemaal afgesloten wilt zijn van de buitenwereld.

©Wesley Akkerman

Draagcomfort is top, bediening laat steken vallen

Verder zitten de Huawei FreeClip 2-oortjes opvallend prettig. Je hangt ze als het ware aan je oor en schuift ze daarna simpelweg naar de plek die voor jou goed voelt. Zitten ze hoger fijner, dan zet je ze iets omhoog. Liever wat lager, dan laat je ze wat meer zakken. Fijn is ook dat ze bij de meeste oorbellen niet in de weg zitten, dus je hebt best veel speelruimte voor de pasvorm. En als leuke extra: ze vallen op als een soort sieraad – je oogt meteen wat modieuzer met deze dingen.

Dat gezegd hebbende zijn we minder te spreken over de fysieke bediening. Het is fijn dat je kunt vegen en tikken, maar juist dat tikken op de dunne rand (de C-brug) werkt minder betrouwbaar dan je hoopt. Eén tik doet gelukkig niets, want die maak je soms al per ongeluk. Alleen: als je wél bewust een tik- of drukbeweging probeert te doen, pakt de brug dat lang niet altijd. Of je nu net te zacht drukt of net niet snel genoeg bent, het resultaat is hetzelfde: we grepen uiteindelijk toch steeds naar onze smartphone om te pauzeren, te skippen of het volume aan te passen.

Daarnaast helpt het ook niet dat je voor Huawei-producten apps moet downloaden die niet gewoon in de Google Play Store staan. Je moet eerst AppGallery van Huawei downloaden en vervolgens AI Life installeren. Android geeft zelfs een flinke waarschuwing en dat voelt niet bepaald geruststellend. Ga je toch door, dan krijg je wel een overzichtelijke manier om de Huawei FreeClip 2 te beheren. Aan de app zelf ligt het dus niet.

Huawei Freeclip 2 kopen?

Met een prijskaartje van pakweg 200 euro moet je diep in de buidel tasten voor de Huawei Freeclip 2. Maar daar krijg je dan ook wel de meest comfortabele open-ear-oordoppen van dit moment voor terug. Koppel dat aan een warme en vertrouwde audiobeleving en je houdt een set over die in deze categorie zijn weerga niet kent. Het gedoe met de app en de bediening is vervelend, zeker op dit prijspunt, dus hopelijk doet de fabrikant daar nog iets mee.

▼ Volgende artikel
Death Stranding: Director’s Cut nu speelbaar via Xbox Game Pass
Huis

Death Stranding: Director’s Cut nu speelbaar via Xbox Game Pass

Microsoft heeft de Xbox Game Pass-titels van de komende wekend aangekondigd. Onder de games die naar de dienst komen valt ook Death Stranding: Director's Cut, die sinds vandaag op Game Pass staat.

De nieuwe Xbox Game Pass-toevoegingen werd via Xbox Wire aangekondigd. Daar valt ook meer informatie over de verschillende games die naar de abonnementsdienst komen te lezen.

Death Stranding

De Director's Cut van Death Stranding is daarbij een van de meest opvallende toevoegingen. Het spel van Hideo Kojima kwam in eerste instantie alleen op PlayStation-consoles uit, maar kwam daarna ook naar Xbox. Kojima bedacht hiervoor de Metal Gear-reeks en staat bekend om zijn vaak duizelingwekkende concepten en haast onnavolgbare verhalen in zijn games. Inmiddels is ook een vervolg op Death Stranding uitgekomen op PlayStation 5, maar die is nog niet op andere platforms beschikbaar.

In Death Stranding maken we kennis met een Amerika dat uit elkaar is gevallen doordat de grens tussen deze wereld en het dodenrijk vervaagt. De wereld wordt geteisterd door unieke regenbuien die niet alleen levende wezens en materialen in extreem snel tempo verouderen, maar ook een soort geesten (BT's) laten verschijnen. Als gevolg hiervan is de samenleving in de VS uit elkaar gevallen en zijn de overgebleven steden afgesloten, vaak ondergrondse forten die geen contact met elkaar hebben.

Spelers besturen Sam Porter Bridges - gespeeld door The Walking Dead-ster Norman Reedus - die door Amerika trekt en pakketjes tussen de verschillende vestigingen vervoert. Ondertussen probeert hij de steden aan een netwerk te verbinden, zodat de samenleving langzaam maar zeker weer in contact met elkaar komt en materialen kunnen uitwisselen via het netwerk. Sam heeft daarnaast de unieke eigenschap de hierboven genoemde BT's te zien. Hij weet zelfs wanneer hij ze nadert doordat hij een speciale baby bij zich draagt met soortgelijke paranormale gaven.

View post on X

De Xbox Games Pass-toevoegingen

Hieronder zijn alle toevoegingen aan Xbox Game Pass van de komende weken te zien.

  • Death Stranding: Director’s Cut (Xbox Series-consoles, pc en cloud) vanaf vandaag beschikbaar via Game Pass Ultimate, Premium, PC Game Pass

  • Ninja Gaiden: Ragebound (Xbox Series-consoles, pc en cloud) vanaf vandaag beschikbaar via Game Pass Ultimate, Premium, PC Game Pass

  • RoadCraft (pc) vanaf vandaag beschikbaar via Game Pass Ultimate, Premium, PC Game Pass

  • The Talos Principle 2 (Xbox Series-consoles en pc) vanaf 27 januari beschikbaar via Game Pass Ultimate, Premium, PC Game Pass

  • Anno: Mutationem (console, pc en cloud) vanaf 28 januari beschikbaar via Game Pass Ultimate, Premium, PC Game Pass

  • Drop Duchy (console, pc en cloud) vanaf 28 januari beschikbaar via Game Pass Ultimate, Premium, PC Game Pass

  • MySims: Cozy Bundle (pc) vanaf 29 januari beschikbaar via Game Pass Ultimate, PC Game Pass

  • Warhammer 40,000: Space Marine 2 (Xbox Series-consoles, pc en cloud) vanaf 29 januari beschikbaar via Game Pass Ultimate, Premium, PC Game Pass

  • Indika (Xbox Series-consoles, pc en cloud) vanaf 2 februari beschikbaar via Game Pass Ultimate, PC Game Pass

  • Final Fantasy 2 (Xbox Series-consoles, pc en cloud) vanaf 3 februari beschikbaar via Game Pass Ultimate, Premium, PC Game Pass

Deze games verdwijnen op 31 januari van Xbox Game Pass:

  • Citizen Sleeper 2: Starward Vector (console, pc en cloud)

  • Lonely Mountains: Snow Riders (console, pc en cloud)

  • Orcs Must Die! Deathtrap (console, pc en cloud)

  • Paw Patrol World (console, pc en cloud)

  • Shady Part of Me (console, pc en cloud)

  • Starbound (console, pc en cloud)

Nieuw op ID: het complete plaatje

Misschien valt het je op dat er vanaf nu ook berichten over games, films en series op onze site verschijnen. Dat is een bewuste stap. Wij geloven dat technologie niet stopt bij hardware; het gaat uiteindelijk om wat je ermee beleeft. Daarom combineren we onze expertise in tech nu met het laatste nieuws over entertainment. Dat doen we met de gezichten die mensen kennen van Power Unlimited, dé experts op het gebied van gaming en streaming. Zo helpen we je niet alleen aan de beste tv, smartphone of laptop, maar vertellen we je ook direct wat je erop moet kijken of spelen. Je vindt hier dus voortaan de ideale mix van hardware én content.