In dit blog-bericht deel ik mijn bevindingen uit het verdiepen in Python als freelance Java(script) developer. Het is als softwareontwikkelaar namelijk van belang dat ik continu nieuwe én bestaande technieken leer en bijhoud.
In de softwarewereld worden nieuwe technieken aan de lopende band ontwikkeld. Maar soms is er ook een stijgende vraag naar bestaande, oudere, technieken zoals Python.
Kijkende naar Google Trends in Nederland van de afgelopen jaren, zie je een aardige groei voor de zoekterm "Python". Afgelopen tijd heb ik zelf ook het gevoel dat het aantal Python-opdrachten groeit, kijkende naar de (vaste & zzp/freelance) opdrachten die langs mij komen.

Daarnaast vind ik het niet alleen belangrijk dat ik continu (voor mij) nieuwe technieken aanleer en ervaring opdoe, maar ik vind het ook gewoon leuk.
Zoals eerder genoemd, zal ik in deze blog post uiteenzetten wat mij opvalt of wat voor mij nieuwe is aan Python, in vergelijking met Javascript (ES6) en Java, waar ik veel mee werk.
1. NumPy
Hoewel het een third-party library is, wil ik toch even de kracht van NumPy benoemen.
NumPy is an open source project that enables numerical computing with Python. (numpy.org)
Wat ik met name interessant vind, is het gemak waarop je op iedere element uit een Numpy-array een berekening kunt loslaten. Bijvoorbeeld:
Python
1import numpy as np
2
3# Een numpy array maken
4arr = np.array([1, 2, 3, 4, 5])
5
6# Een operatie uitvoeren op alle elementen
7result = arr * 2
8
9print(result) # Output: [ 2 4 6 8 10]Op regel 7 zie je hoe simpel het is om alle elementen te vermenigvuldigen: arr * 2. Als je arr zou willen filteren
op elementen die groter of gelijk zijn aan 3, dan doe je simpelweg: arr[arr >= 3]. Handig toch? En dat is slechts het
begin van Numpy!
2. Lezen van bestanden met Python
Zo nu en dan schrijf ik een Node.js-script om een bestand in te lezen en daar iets mee te doen. Hiervoor gebruik ik
de fs-module:
JavaScript
1const fs = require('fs');
2
3const fileName = 'example.txt';
4fs.readFile(fileName, 'utf8', (err, data) => {
5 if (err) {
6 console.error('Error reading file:', err);
7 return;
8 }
9
10 console.log(data);
11});Om het vergelijkbare te doen in Python, kun je gebruik maken van de open-functie in combinatie met een with
-statement. Die with-statement doet me overigens vergelijkbaar met Java's try-with-resources block:
Python
1with open('example.txt', 'r') as f:
2 inhoud = f.read()
3
4print(inhoud)3. Data-analyses met Pandas
Een paar jaar geleden heb ik voor een opdracht een aantal data-analyses moeten uitvoeren o.b.v. data uit verschillende CSV-bestanden. Daarvoor had ik met Node.js & NPM een script gemaakt. Voor het efficiënt inlezen en alle rijen langs te gaan, moest ik gebruik maken van een externe NPM library. Al met al moest ik relatief veel code schrijven in vergelijking met Pandas! (Note: Er zijn npm libraries die op Pandas zijn geïnspireerd/gebaseerd of óók efficiënt zijn, maar die negeer ik voor nu even).
pandas is a fast, powerful, flexible and easy to use open source data analysis and manipulation tool, built on top of the Python programming language. (pandas.pydata.org)
Stel ik heb het volgende CSV-bestand people.csv met namen en leeftijden van personen:
| Name | Age |
|---------|-----|
| John | 25 |
| Emma | 30 |
| Michael | 22 |
| Sophia | 28 |
| William | 35 |Als ik alle personen wil filteren op leeftijd >= 30, doe ik dat met enkele regels code:
Python
1import pandas as pd
2
3df = pd.read_csv('people.csv')
4filtered = df[df['Age'] >= 30]
5print(filtered)
6
7# Output:
8# Name Age
9# 1 Emma 30
10# 4 William 35Lekker makkelijk! Pandas kan natuurlijk nog véél meer, en daar ga ik zeker nog mee experimenteren.
4. List comprehensions
List Comprehensions is a very powerful tool, which creates a new list based on another list, in a single, readable line. (learnpython.org)
Met list comprehensions kun je in één regel een lijst maken, transformeren en filteren. In ES6 zou ik dat doen
m.b.v. .map() of .filter(). Python kent deze ook, echter, in de Python-wereld gebruikt men liever list
comprehensions.
Stel ik heb een class Person met eigenschappen name en age, dan kan ik een lijst daarvan (regel 10-16) filteren op
leeftijd (regel 19) en printen met list comprehensions (regel 22):
Python
1class Person:
2 def __init__(self, name, age):
3 self.name = name
4 self.age = age
5
6 def __str__(self):
7 return self.name + "=" + str(self.age)
8
9
10people = [
11 Person("John", 25),
12 Person("Emma", 30),
13 Person("Michael", 22),
14 Person("Sophia", 28),
15 Person("William", 35)
16]
17
18# Filter met list comprehension
19filtered = [person for person in people if person.age >= 30]
20
21# Print met list comprehension
22print([str(person) for person in filtered])
23
24# Output:
25# ['Emma=30', 'William=35']5. Lambda functies in Python
Toen lambda's voorbijkwamen in één van de online tutorials die ik volgde, kreeg ik even flashbacks naar mijn tijd aan de universiteit. Daar had ik het vak Functional Programming waar we met Haskell leerde programmeren. En daar deed mij de lambda syntax in Python mij even aan denken, die is namelijk als volgt:
Python
1sum = lambda x, y: x + y
2
3print(sum(3, 4)) # Output: 7Je moet expliciet de keyword lambda gebruiken hier. Met ES6 is zoiets niet nodig en doe je simpelweg:
JavaScript
1(x, y) => x + y6. Function arguments by keywords
Zo nu en dan is het handig om functieparameters bij de naam te noemen. Bijvoorbeeld met Javascript, als wilt voorkomen dat je code breekt als de volgorde van de parameters veranderen, om wat voor reden dan ook. In dat geval kun je gebruik maken van object-destruction:
JavaScript
1const divide = ({a, b}) => a / b;
2divide({b: 2, a: 10}); // Output: 5In het bovenstaand voorbeeld geef ik expliciet aan wat de waarde van a en b moet zijn bij het aanroepen
van divide.
Hetzelfde gaat met Python wat makkelijker — object destruction is namelijk niet nodig. Hier zie je het principe function arguments by keywords in Python:
Python
1def divide(a, b):
2 return a / b
3
4
5divide(b=2, a=10) # Output: 5.07. Variabel scopes
De global-keyword (Python vs. Javascript)
Als je in Python, binnen een functie, gebruik wilt maken van een globale, buiten de functie gedefinieerde, variabele,
dan moet je de global-keyword gebruiken.
In de volgende Python code-block zie je de variabele my_num = 10. Vervolgens, wordt in myfunction een waarde
van 12 aan my_num gegeven. Echter, my_num binnen myfunction is een nieuwe variabele. Dus in de output zie je
twee verschillende waardes:
Python
1my_num = 10
2
3
4def myfunction():
5 my_num = 12
6 print(my_num)
7
8
9myfunction()
10print(my_num)
11
12# Output:
13# 12
14# 10Als je wilt dat myfunction de waarde toekent aan de globale variabele, dan moet je in de functie aangeven dat je de
globale my_num gaat gebruiken d.m.v. global mynum. In dat geval zie je dat de output anders is:
Python
1my_num = 10
2
3
4def myfunction():
5 global my_num # <- Verschil
6 my_num = 12
7 print(my_num)
8
9
10myfunction()
11print(my_num)
12
13# Output:
14# 12
15# 12Afkomstig uit de Java(script)-wereld, zal dit voor mij wennen zijn. Met Javascript definieer je een nieuwe variabel
met var, const of let. Op dat moment weet je al dat dat de eerste definitie is in tegenstelling tot Python. Je
hoeft verder dus niet aan te geven in een functie dat je de globale variabele wilt gebruiken.
Het voorgaande voorbeeld zou je in Javascript als volgt doen:
JavaScript
1let my_num = 10;
2
3const myfunction = () => {
4 my_num = 12;
5 console.log(my_num);
6};
7
8myfunction();
9console.log(my_num);
10
11// Output:
12// 12
13// 12In dit geval pakt myfunction direct de globale my_num.
De nonlocal-keyword
Nog zoiets wat wennen zal zijn voor mij: nonlocal. Met nonlocal geef je binnen een sub-functie aan dat de variabele
van de omringende functie moet worden gebruikt.
In het volgende voorbeeld zie je de functie outer met een sub-functie inner. De output is wederom verschillend:
Python
1def outer():
2 my_num = 10
3
4 def inner():
5 my_num = 12
6 print(my_num)
7
8 inner()
9 print(my_num)
10
11
12outer()
13
14# Output:
15# 12
16# 10Als je nu in inner aangeeft dat inner de my_num van de omliggende functie moet gebruiken, dan zal de output
verschillen:
Python
1def outer():
2 my_num = 10
3
4 def inner():
5 nonlocal my_num # <- Verschil
6 my_num = 12
7 print(my_num)
8
9 inner()
10 print(my_num)
11
12
13outer()
14
15# Output:
16# 12
17# 12Als je nonlocal in de outer functie gebruikt, krijg je overigens een foutmelding.
Conclusie
Alhoewel mijn Python kennis nog relatief oppervlakkig is, heb ik al veel geleerd. Zo kan ik nu beter begrijpen waarom je eerder voor Python zou kiezen voor data-analyses ten opzichte van andere talen.
Komende tijd zal ik mijn Python kennis verbeteren. In de toekomst ga ik dan ook zeker freelance Python opdrachten aannemen.
Mocht je op zoek zijn naar een goede resource om Python te leren, dan raad ik learnpython.org aan.
