Mijn eerste duik in Python als Javascript en Java programmeur

Nyef
Nyef
Mijn eerste duik in Python als Javascript en Java programmeur

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.

Python stijgend in Google Trends Nederland

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   35

Lekker 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: 7

Je moet expliciet de keyword lambda gebruiken hier. Met ES6 is zoiets niet nodig en doe je simpelweg:

JavaScript

1(x, y) => x + y

6. 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: 5

In 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.0

7. 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# 10

Als 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# 12

Afkomstig 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// 12

In 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# 10

Als 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# 12

Als 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.

Delen

Ervaren software engineer nodig?

Ik help bedrijven met softwareoplossingen (SaaS, automatiseren en meer) — van backend tot frontend. Neem vrijblijvend contact op om te kijken hoe ik kan bijdragen aan jouw project.

  • Robuuste backend: Java/Kotlin, SQL, Spring Framework
  • Gebruiksvriendelijke front-end: Next.js, React, Typescript, ES6
  • Snelle doorontwikkeling: Continuous integration & deployment, Jenkins
  • Efficiënte samenwerking: Agile, Scrum, Jira, Git, Bitbucket, GitHub
  • Freelance software-ontwikkelaar uit Arnhem