0% found this document useful (0 votes)
32 views

ML Python Beginners 01 2024

The document outlines a training on Python for beginners. It covers two modules, with module 1 covering topics like what Python is, IDEs, variables, operators, expressions, and statements. Module 2 will cover musicXML and music21 libraries.

Uploaded by

Alberto
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views

ML Python Beginners 01 2024

The document outlines a training on Python for beginners. It covers two modules, with module 1 covering topics like what Python is, IDEs, variables, operators, expressions, and statements. Module 2 will cover musicXML and music21 libraries.

Uploaded by

Alberto
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 87

Training:

Python for Beginners

André Zimmer
12.01.-20.01.2023 [email protected]
Contents
Module 1:

What is Python?

What are IDEs and Jupyter?

Programming with Python:

Operators, Variables, Structures

Conditional expressions, loops

Functions

...

01/2023 2
Contents
Module 2:

musicXML

music21

01/2023 3
Python Basics

Module 1

01/2023 4
What is Python?

Python is an interpreted programming language.

Python was developed and introduced 1991 by Guido van
Rossum.

Currently Python 3.x which was released 2008 is commonly used.

Programming with Python is a lot of fun!

You will learn how to program "pythonic”!

Some of the structure of Python code is created by using leading
white spaces!

01/2023 5
What is Python?

Today Python is one of the most used and liked programming
languages:

https://insights.stackoverflow.com/survey/2020

01/2023 6
What is Python?
Why do people like Python?

C++ : Java:

#include<stdio.h> public class JavaHelloWorldProgram {

main() public static void main(String []args) {


{ System.out.println("Hello World");
printf("Hello World"); }
} }
Python:
print("Hello World")

01/2023 7
What is Python?
Why do people like Python:

Huge ecosystem has evolved:

Excellent libraries for people interested in machine learning:

Numpy + Scipy

Pandas

Scikit Learn

Tensorflow, PyTorch, XGBoost...

01/2023 8
What is Python?
Why do people like Python:

Huge ecosystem has evolved:

Visualization, SQL, web, games, music:

Matplotlib, Seaborn, Plotly...

SQLAlchemy

Beautiful Soup, Django...

PyGame

Pyaudio, music21

01/2023 9
What is Python?
Why do people like Python:

Huge ecosystem has evolved:

PyCon

Excellent documentation

Excellent help at Stack Overflow

Local groups

ChatGPT

01/2023 10
What is Python?
Some code: a function

def print_list_of_words(word_list):
for word in word_list: definition of a variable, here a list
print(word)

new_word_list = ["Welcome","Python","beginner","class"]
print_list_of_words(new_word_list)
calling our function
>>Welcome the result of the function call
>>Python
>>beginner
>>class

01/2023 11
What is Python?
def print_list_of_words_to_one_line(word_list):
line2print = ""
for word in word_list:
line2print = line2print + word + " "
line2print = line2print[:-1] + "."
print(line2print)

new_word_list = ["Welcome","Python","beginner","class"]
print_list_of_words_to_one_line(new_word_list)

>>Welcome Python beginner class.

01/2023 12
What is an IDE?
IDE stands for integrated development environment

For Python, there are a few options available:

PyCharm

Visual Studio Code

Eric6

Vim

Many more

01/2023 13
What is an IDE?

An IDE makes developing code easy, using some nice features:

Syntax highlighting

Auto complete key words, variable names

Automatic code formatting

Debugging support

GUI for version repository

...

01/2023 14
What is an IDE?

https://blog.jetbrains.com/wp-content/uploads/2014/09/pycharm-
BDD1.png
01/2023 15
What is Jupyter?

Jupyter is an interactive development environment (for Julia,
Python, R and many more) in your web browser.

It is excellent for data exploration and data scientists love it!

Together with Python, Jupyter can use widgets, which further
enhances the interactive aspect of Jupyter.

Disadvantages are:

Memory usage

Reliability of developed code

Version control
01/2023 16
Python Basics - Variables
a_short_text = ‘This is a short text’
n = 10 Variable
Assignment Operator
e = 2.71
Value
training_done = False


A value can get assigned to a variable by using the = operator.

Nothing has to be declared, Python chooses the data type.

Here we have a string, an integer, a float and a boolean.

01/2023 17
Python Basics - Variables
type(a_short_text)
>> <class 'str'>
type(n)
>> <class 'int'>
type(e)
>> <class 'float'>
type(training_done)
>> <class 'bool'>

The type of a variable can get checked by using type().

01/2023 18
Python Basics - Casting
It is possible to change the type of a variable:
type(str(1))
>> <class 'str'>
type(str(1.0))
>> <class 'str'>
type(int(1.0))
>> <class 'int'>
type(int('one'))
>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'one'

01/2023 19
Python Basics - Variables
Rules and conventions for variable names:

Variable names must not start with numbers or strange characters
(esp. not space).

Upper and lower case matters, normally variables should be lower
case.

Variable names consisting of only one letter should be avoided.

Variable names should be meaningful:

n_people_in_training

ratio_awake_students

01/2023 20
Python Basics - Variables
Rules and conventions for variable names:

Using Python keywords is actually somewhat possible in Python,
but do not do it!!! - EVER!!!

It is possible to ask Python which keywords it currently knows:
import keyword
keyword.kwlist
>> ['False', 'None', 'True', 'and', 'as', 'assert', 'async',
'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else',
'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in',
'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return',
'try', 'while', 'with', 'yield']

01/2023 21
Python Basics - Operators
Basic Python operators:

Arithmetic: +, -, *, /, %, **, //

Comparison: ==, !=, <>, >, <, >=, <=

Assignment: =, +=, -=, *=, /=, %=, **=, //=

Bitwise: &, |, ^, ~, <<, >>

Logical: and, or, not

Membership: in, not in

Identity: is, is not

01/2023 22
Python Basics - Expressions
An expression is a combination of variables,values and operators
22 + 27
>> 49
n + e
>> 12.71
n + 2 * e Remember, n is an
>> 15.42 integer and e a float!

01/2023 23
Python Basics - Statements
A statement is a piece of code that creates or does something new.
n = n * 2
print(word)

When in a normal Python interpreter, a statement gets executed


when the user hits enter.

01/2023 24
Python Basics - Strings
In Python a string is a sequence. A sequence is an ordered collection
of values. This makes a string an ordered collection of characters. In
Python you can do quite a few operations on strings.

f1_driver = 'Eddie Irvine'


for letter in f1_driver:
print(letter)
>> E
>> d
>> d
...

01/2023 25
Python Basics - Strings
Single elements of a string can get accessed using an index with
square brackets:
f1_driver = 'Eddie Irvine'
print(f1_driver[0])
>> E
print(f1_driver[3])
>> i
print(f1_driver[5])
>>
print(f1_driver[-1])
>> e

01/2023 26
Python Basics - Strings
A colon allows what is called "slicing":
f1_driver = 'Eddie Irvine'
print(f1_driver[0:5])
>> Eddie
print(f1_driver[0:6])
>> Eddie
print(f1_driver[6:])
>> Irvine
print(f1_driver[3:8])
>> ie Ir
print(f1_driver[-6:])
>> Irvine
print(f1_driver[::-1])
>> enivrI eiddE

01/2023 27
Python Basics - Strings
Some functions and methods:
f1_driver = 'Eddie Irvine'
print(len(f1_driver)) function
>> 12
print(f1_driver.lower()) method
>> eddie irvine
space_location = f1_driver.find(' ')
first_name = f1_driver[0:space_location]
last_name = f1_driver[space_location+1:]
Or, the Pythonic way:
first_name,last_name = f1_driver.split(' ')

01/2023 28
https://docs.python.org/3/library/stdtypes.html#string-methods
Python Basics - Printing
A Python program that talks to you is a good program:
file_name = 'some_data.csv'
data = read_data(file_name)
n_rows = len(data)
msg = 'Just read ' + file_name + ' containing ' + n_rows + ' rows of data.'
>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
msg = 'Just read ' + file_name + ' containing ' + str(n_rows) + ' rows of
data.'
print(msg)
>> Just read some_data.csv containing 10 rows of data.

01/2023 29
Python Basics - Printing
The old way of creating a message:
file_name = 'some_data.csv'
data = read_data(file_name)
n_rows = len(data)
print('Just read %s containing %d rows of data.'%(file_name, n_rows))
>> Just read some_data.csv containing 10 rows of data.

long_number = 1/9
print('A long number, but short: %.2f.'%long_number)
>> A long number, but short: 0.11.

01/2023 30
Python Basics - Printing
Printing with f-strings:
file_name = 'some_data.csv'
data = read_data(file_name)
n_rows = len(data)
print('Just read {0} containing {1} rows of data.'.format(file_name, n_rows))
>> Just read some_data.csv containing 10 rows of data.

long_number = 1/9
print('A long number, but short: {:.2f}.'.format(long_number))
>> A long number, but short: 0.11.

01/2023 31
https://docs.python.org/3/library/stdtypes.html#str.format
Python Basics - Printing
Printing with f-strings:
file_name = 'some_data.csv'
data = read_data(file_name)
n_rows = len(data)
print(f'Just read {file_name} containing {n_rows} rows of data.')
>> Just read some_data.csv containing 10 rows of data.

long_number = 1/9
print(f'A long number, but short: {long_number:.2f}.')
>> A long number, but short: 0.11.

01/2023 32
https://www.python.org/dev/peps/pep-0498/
Python Basics

Exercise 1

01/2023 33
Python Basics - Lists
Lists are similar to strings. But lists are ordered sequences of values
in general:
integer_list = [1,2,3,4,5]
float_list = [1.0, 2.0, 3.0,]
string_list = ['close','to','first','break']
mixed_list = [1, 2.0, 'three']
empty_list = list() Good structure
for a matrix?
other_empty_list = []
nested_list = [1,2,3,[4,5,6], [[1,2,3],[9,8,7],[4,5,6]]]

01/2023 34
Python Basics - Lists
Just like strings, elements of a list can get accessed by slicing:

integer_list = [1,2,3,4,5]

print(integer_list[0:3])
>> [1, 2, 3]
print(integer_list[:])
>> [1, 2, 3, 4, 5]
print(integer_list[-100:])
>> [1, 2, 3, 4, 5]

01/2023 35
Python Basics - Lists
Lists come with many methods:

integer_list = [1,2,3,4,5]
integer_list.append(-10)
print(integer_list)
>> [1, 2, 3, 4, 5, -10]
integer_list.sort()
print(integer_list)
>> [-10, 1, 2, 3, 4, 5]
integer_list += [20,30]
print(integer_list)
>> [-10, 1, 2, 3, 4, 5, 20, 30]

01/2023 36
https://docs.python.org/3/tutorial/datastructures.html?
Python Basics - Lists
Lists come with many methods:

integer_list = [-10, 1, 2, 3, 4, 5, 20, 30]


integer_list.pop()
>> 30
integer_list.remove(2)
print(integer_list)
>> [-10, 1, 3, 4, 5, 20]
integer_list.reverse()
print(integer_list)
>> [20, 5, 4, 3, 1, -10]

01/2023 37
https://docs.python.org/3/tutorial/datastructures.html?
Python Basics - Loops
Loops in Python can get created by the while or for statement:
while: for:
integer_list = [1,2,3] integer_list = [1,2,3]
counter = 0 for element in integer_list:
while counter <= 2: print(element)
print(integer_list[counter])
counter += 1
>> 1 This is the
>> 1 >> 2 pythonic
>> 2 >> 3 solution.
>> 3

01/2023 38
Python Basics - Loops
Loops in Python can get created by the while or for statement:
integer_list = [1,2,3]
sqrd_list = []
for el in integer_list:
4 leading sqrd_list.append(el**2)
spaces as
indentation: print(sqrd_list)
>> [1,4,9]

In general Python can iterate through everything that is an iterator.

01/2023 39
https://docs.python.org/3/library/
Python Basics

Exercise 2

01/2023 40
Python Basics - Loops
Using range often helps to set up a loop:
end increment (optional)
start
some_str = 'Who will win F1?'
for idx in range(0,len(some_str),2):
print(some_str[idx])

>>W
>>o
>>w
...

01/2023 41
Python Basics - Conditions
Using if, elif and else, different parts of the code can be executed:
if condition is True:
print("I am in this part of the code.")
else:
print("I will execute this")

4 leading
spaces:

01/2023 42
Python Basics - Conditions
Using if, elif and else, different parts of the code can be executed:
if condition is True:
print("I am in this part of the code.")
elif condition_two:
print("Now, I am here.")
the elif-part is
else:
optional
print("I will execute this")

01/2023 43
Python Basics - Conditions
Using if, elif and else, different parts of the code can be executed:
input_list = [1,2,4,-2]
sqrd_list = []
for el in input_list:
squared_val = el ** 2
if el < 0:
squared_val *= -1
Additional 4 sqrd_list.append(squared_val)
leading spaces:
print(sqrd_list)
>> [1,4,16,-4]

01/2023 44
Python Basics - Conditions
Using if, elif and else, different parts of the code can be executed:
sqrd_list = []
for el in input_list:
if el < 0:
square_val = -1 * (el ** 2)
elif el >=2:
square_val = el ** 2
else:
square_val = el
sqrd_list.append(square_val)
print(sqrd_list)

01/2023 45
Python Basics - Conditions
Nested if-else:
if a < 0:
print('a is negative')
elif a >= 0 and a < 5:
print('a is between zero and 5.')
else:
Backslash for
if a >= 1000: multiline string:
print('a is really big.')
else:
print('a is bigger than 5 \
but below 1000.')

01/2023 46
Python Basics - Conditions
Some more conditions:
isinstance(a,str)
type(a) == int
a < 2
a > 5
(a < 2) and (a > 5)
2 > a > 5
len(a_list) > 0
True or False?

'a' in 'Formula 1'


1 in 'Formula 1'

01/2023 47
Python Basics – Keyword: break
Interesting keyword:
for idx in range(0,10):
print(idx)
if idx >= 3:
break
>>0
>>1
>>2
>>3

01/2023 48
Python Basics

Exercise 3

01/2023 49
Python Basics

Exercise 4

01/2023 50
Python Basics - Functions
A function is a stored piece of code that can be used at any time.
We have already used a function: type().
It takes an input value and returns some information:

type(n)
>> <class 'int'>

01/2023 51
Python Basics - Functions
To define our own functions, we need the def keyword, a function
name, optional inputs, a colon, a statement and an optional return
value:
def keyword function name Input values colon

def add_two_values(value_1, value_2):


sum = value_1 + value_2
statement
return sum
return value

01/2023 52
Python Basics - Functions
Python understands local and global variables. Unless made global,
a variable, only defined in a function is only known to the function:
def add_two_values(value_1, value_2):
sum = value_1 + value_2
return sum

the_sum = add_two_values(1,4)
print(sum)
>> <built-in function sum>

01/2023 53
Python Basics - Functions
What just happened?
Well, we used a variable name for a function that is known to Python!
So lets rewrite the function and try again:
def add_two_values(value_1, value_2):
calculated_sum = value_1 + value_2
return calculated_sum

the_sum = add_two_values(1,4)

print(calculated_sum)

>> Traceback (most recent call last):


File "<stdin>", line 1, in <module>
NameError: name 'calculated_sum' is not defined

print(the_sum)

>> 5

01/2023 54
Python Basics - Functions
A funny Python keyword:

def add_two_values(value_1, value_2):


pass

This function does nothing!


The "pass" is just a placeholder for later code. If you just define a
function and do nothing, your IDE will complain and warn you. If you
are not using one, or it does not complain, Python will.

01/2023 55
Python Basics - Functions
The "return" keyword:
def add_two_values(value_1, value_2):
return 1
if value_1 != 0:
return value_1 + value_2

Return immediately returns the value behind it. This function will
always return a 1.

01/2023 56
Python Basics - Functions
The lambda function:
lambda keyword input arguments

short_func = lambda x, y: 2 + x*3 - y ** 2


short_func(1,2)
>> 1 some statement
behind colon
short_func(3,2)
>> 7

01/2023 57
Python Basics - Functions

One more lesson about functions:


Do not reinvent the wheel. Python can add up two numbers, by using
the + operator. This function was pointless.
Before implementing anything, check if Python or a module you are
using, already does what you want or search the internet!

01/2023 58
Python Basics - Tuples
In general tuples are a immutable comma-separated sequence of
values. Usually, they are enclosed by round parentheses:
new_tuple = 1,2,3,4
other_tuple = (1,2,3,4) #This is better
One element tuples have to end with a comma:
short_tuple = 1,
not_a_short_tuple = (1) #Not a tuple!
other_short_tuple = (1,)

01/2023 59
Python Basics - Tuples
Empty tuples:
empty_tuple = tuple()
other_empty_tuple = ()

String to tuple:
funny_tuple = tuple('Formula 1')
print(funny_tuple)
>> ('F', 'o', 'r', 'm', 'u', 'l', 'a', ' ', '1')

01/2023 60
Python Basics - Tuples
Tuples are good for assigning variables:
email_address = '[email protected]'
name, domain = email_address.split('@')
counter, max_iterations = 0, 100
Swap the variables a and b:
temp = a
a = b
b = temp
a,b = b, a #better and shorter!
01/2023 61
Python Basics - Tuples
Returning more than one value from a function is done with tuples:

def small_mid_max_from_list(input_list):
min = min(input_list)
max = max(input_list)
mid = (min + max) / 2
return min,mid,max

01/2023 62
Python Basics - Sets
Sets are similar to lists, but only contain unique values:
list_1 = [1,2,3,4,4,4,2,7]
list_2=[2,2,4,5,6,7,8,9,10]
set_1 = set(list_1)
set_2 = set(list_2)
set_1
>> {1, 2, 3, 4, 7}
set_1 and set_2
>> {2, 4, 5, 6, 7, 8, 9, 10}
set_1 or set_2
>> {1, 2, 3, 4, 7}
set_1 – set_2
>> {1, 3}

01/2023 63
Python Basics

Exercise 5

01/2023 64
Python Basics – Modules
Usually a file can be anywhere on a computer, which means a
path will have to be supplied. Now on Linux, folders are separated
by forward slashes and there are no drive letters. Windows knows
c:\ using a back slash. So getting a Python program to work in
these two environments can get tricky. However, Python does
supply options. They are supplied through the os or the pathlib
module: import os
import pathlib
By using functions and methods inside of these modules, Python
can take care of the issues described.
01/2023 65
Python Basics – Import a Module
By importing modules, it is possible to expand the functionality of
Python. There are a few ways to import new modules.

import os # Imports everything in os. Functions get


accessed by os.<func_name>
from pathlib import Path # Only imports Path
import pandas as pd # Imports everything in Pandas. Functions get
accessed with the pd. prefix (we can choose
what we like)
from f1_helpers import * # Imports everything in f1_helpers

01/2023 66
Python Basics – Read Files
Computer programs are supposed to calculate things. For this
they need to be able to read data from somewhere. This could be
from a csv file:
Using context manager:
csv_file = open('f1_stats.csv','r') with open('f1_stats.csv','r') as csv_file:
csv_data = csv_file.readlines() csv_data = csv_file.readlines()
csv_file.close()

Using 'r', activate


read mode, to write
use 'w', 'a' appends

01/2023 67
Python Basics

Exercise 6

01/2023 68
Python Basics - Dictionaries
Dictionaries are similar to lists but access the values, using keys,
hence it maps keys to values:
empty_dict = dict()
other_empty_dict = {}
driver_2_short = {'M. Schumacher' : 'MSC',
'J. Montoya': 'JPM',
'S. Vettel' : 'VET'}
name_abbr = driver_2_short['M. Schumacher']
print(f'M. Schumacher was abbreviated as : {name_abbr}.')
>> M. Schumacher was abbreviated as : MSC.

01/2023 69
Python Basics - Dictionaries
Most of the time dictionary keys will be strings, but they can be
anything:
pos_2_points = {1 : 25,
2 : 18,
3 : 15}
print(f'Coming in first, scores you {pos_2_points[1]} \
championship points')
>> Coming in first, scores you 25 championship points

01/2023 70
Python Basics - Dictionaries
Check for existing keys:

pos_2_points = {1 : 25, driver_2_short = {'M. Schumacher' : 'MSC',


2 : 18, 'J. Montoya': 'JPM',
3 : 15} 'S. Vettel' : 'VET'}

2 in pos_2_points
>> True
15 in pos_2_points
>> False
'The Stig' in driver_2_short
>> False

01/2023 71
Python Basics - Dictionaries
Iterate through a dictionary:

driver_2_short = {'M. Schumacher' : 'MSC',


'J. Montoya': 'JPM',
'S. Vettel' : 'VET'}

for drv in driver_2_short:


print(drv)
>> M. Schumacher
>> S. Vettel
>> J. Montoya

01/2023 72
Python Basics - Dictionaries
Iterate through a dictionary:

driver_2_short = {'M. Schumacher' : 'MSC',


'J. Montoya': 'JPM',
'S. Vettel' : 'VET'}

for drv in driver_2_short:


print(f'{drv}: {driver_2_short[drv]}')
>> S. Vettel: VET
>> J. Montoya: JPM
>> M. Schumacher: MSC

01/2023 73
Python Basics - Dictionaries
Iterate through a dictionary, the pythonic way:

for drv, abbr in driver_2_short.items():


print(f'{drv}: {abbr}')

>> M. Schumacher: MSC


>> J. Montoya: JPM
>> S. Vettel: VET

01/2023 74
Python Basics

Exercise 7

01/2023 75
Python Basics – Exception Handling
When reading a file, it might not be there, or Python cannot read it
for some reason. This should not crash the whole program, esp.
not without informing the user. For this Python knows exception
handling:
try:
some code
except:
print('Some thing went wrong…') #Optional, but very useful!!!
alternative code

01/2023 76
Python Basics – Exception Handling
When reading a file, it might not be there, or Python cannot read it
for some reason. This should not crash the whole program, esp.
not without informing the user. For this Python knows exception
handling:
try:
some code This print is
a = 1 / 0 optional, but
obviously very
except: useful.
print('Something went wrong. Did you divide by zero?')
alternative code

01/2023 https://docs.python.org/3/tutorial/errors.html?highlight=except#handling-exceptions 77
Python Basics

Exercise
User Input

01/2023 78
Python Basics – Classes
To deal with complicated data structures, it is possible to define a
class:
class Circle():
def __init__(self):
self.x = 0
self.y = 0
self.radius = 1

def get_area(self):
return 3.14 * self.radius ** 2

01/2023 https://docs.python.org/3/tutorial/ 79
classes.html
Python Basics – Classes
Now you might get an idea what the difference between a function
and a method is:
new_circle = Circle()
area = new_circle.get_area()
print(area)
>> 3.14 This method is
a function of the
new_circle.radius = 2 class.
print(new_circle.get_area())
>> 12.56

01/2023 https://docs.python.org/3/tutorial/ 80
classes.html
Python Basics

Exercise C1

01/2023 81
Python Basics

Module 2

01/2023 82
Python Basics – Virtual Environments
Every larger Python project will need to use some modules. To
deal with this requirement, virtual environments can be used:

Fix the version of modules and Python.

Have working combination of modules.

As most variants allow some kind of requirements.txt export, it
is easy to install everything needed on different machine.

01/2023 83
Python Basics – Virtual Environments
Virtual environment options in Python:

Virtualenv

Pyenv (This one, allows multiple Python installations)

Pipenv

Poetry

01/2023 84
Python Basics – Virtual Environments
Virtualenv:
c:\Python35\python -m venv c:\path\to\myenv

c:\path\to\myenv\Scripts\activate.bat

python -m pip install pandas

pip freeze > requirements.txt

python -m pip install -r requirements.txt

01/2023 https://docs.python.org/3/library/ 85
venv.html
Python and Brackets
Brackets, Braces …

( ): Pass arguments to function, even if we have
zero params, Tuple

[ ]: Access element of a sequence, List

{ }: Dictionary, f-String

01/2023 86
We are done!
Thank you very much!
This presentation was prepared for
University of Music and Performing Arts Mannheim
and may not be published or redistributed.

01/2023 87

You might also like