Week 1
Week 1
Week 1
What is Python?
• It is a programming language
• It is readable for human beings
• It is not readable for computers: a python script has to be translated, before
the computer can read and execute it
• It is readable, but it is not a natural language, so it is also quite
inflexible (it is not chat gpt)
• Can leads to errors (using sorted where you have to use sort and vice
versa), that human listeners would easily notice and ignore
• We use so-called monospaced fonts for code
• Python forces you to work structured, and this is the reason it is used
in a lot of places to learn programming
What is Python?
• Python is an interpreted language, that means a Python
script is translated and executed line by line
• Advantage: Easy to write, test and change
• Disadvantage: It leads to slower programs than compiled
languages
• Compiled languages, take advantage of already knowing in the beginning
of a program how data (variables) will be used later in the program
• However: Difference becomes less important as computers
gets faster
What is Python?
• Python is very expandable (swiss army knife)
• Compared to other languages, it is easy to have python
cooperating/communicating with programs written in other faster (compiled)
languages (E.g. Fortran)
• There are a lot of packages for Python, and some have faster programming
languages under the hood
• So Python was always cool, but now is also hip
• Python is used a lot in artificial intelligence/machine learning
Program or Script
• Some people will call a Python program a script
• There used to be a difference:
• Script: code in an interpreted language
• Program: code in a compiled language
• Nobody cares any more, but maybe program sounds a bit more
sophisticated
• I will be a bit messy
Compare my background in cobol (1979)
IDENTIFICATION DIVISION.
PROGRAM-ID. Hello-world.
PROCEDURE DIVISION.
DISPLAY "Hello World".
See: https://www.geeksforgeeks.org/hello-world-in-30-different-languages/
with your future in Python
print("Hello World")
name_2 = name_1 To the variable containing 's1' Python adds a second label 'name_2'.
Now we have one variable containing the string value 's1' with two names 'name_1' and
'name_2'
name_1 = 's2' From the variable containing 's1' the name 'name_1' is removed. Python creates a new variable
containing the value 's2' and adds the name 'name_1' to this new variable.
Now we have one variable containing the value 's2' with label 'name_1' and one variable
containing the value 's1' with label 'name_2'
name_2 = 's3' From the variable containing 's1' the name 'name_2' is removed. If as is the case here, that was
the only name reference to that variable Python's garbage collection will remove this variable.
Now we have one variable with label 'name_1' containing the value 's2'
An example with a mutable variable (a list)
l1 = ['s1', 's2'] Python creates a variable containing the value 's1' and another variable containing the value 's2'.
Now Python creates a variable containing a list with two references, one reference to the variable
containing the value 's1' and another reference to the variable containing the value 's2'. Python now
adds the name 'l1' to that list.
Now we have one variable with the name 'l1' containing a list with the two references, one to a
variable with the value 's1' the other one to a variable containing the value 's2'.
NB! The variables containing 's1' and 's2' have no names but (of course) have id's.
value 's1' the other one to a variable containing the value 's2'
l2=l1 To the variable containing the list with the two references Python adds a second label 'l2'.
l1[0] = 's3' Python creates a variable containing the value 's3', and Python mutates the list, the first reference is
no longer to the variable containing 's1' but to a variable containing 's3', the second reference is still
to a variable containg the value 's2'.
l2 = ['s3', 's4'] From the first list the name 'l2' is removed. As that list is still referenced by the name 'l1' the list will
not be removed by Python's garbage collection.
Next Python creates two variables containing the value 's3' and Python creates another variable
containing the value 's4'. Now Python creates a list containing two references, one reference to the
variable containing the value 's3' and one to the variable containing the value 's4'.
Tricky question
• You have a variable with name 'box_1' containing the string value
'content'
• But you want to have a variable with name 'box_1' containing string
value 'new content'.
• We know variables with a string value are immutable
• Why then does the following work?
box_1 = 'content'
print(box_1) # Onscreen: content
box_1 = 'new content'
print(box_1) # Onscreen: new content
• Answer we didn’t change the old variable, we created a new variable
and gave it the old name.
Slicing (I) The normal case
• Slicing creates a new variable made of parts of another
variable
• Slicing can be used with variables of type list, string, tuple
new_list = existing_list[start:end:step_size]
• Start is inclusive
• End is not inclusive
• The first element is 0, the second is 1, and the last is
len(existing_list)-1
Slicing (I) examples, when all parameters are >= 0
• l1 = [1, 2, 3, 4, 5, 6, 7, 8]
print(l1[0:6:2]) # Remember 0 is the first, 1 is the
second etc # Onscreen: [1, 3, 5]
• print(l1[1:6]) # Takes the default for the step_size
= 1 # Onscreen: [2, 3, 4, 5, 6]
• print(l1[:6:2]) # Takes the default for the start = 0
# Onscreen: [1, 3, 5]
• print(l1[2::2]) # Takes the default for the end =
length - 1 # Onscreen: [3, 5, 7]
You can leave out 1, 2, or 3 parameters
• print(l1[::]) # Takes the defaults for the start = 0,
# for the end = len(l1) – 1,
# for step_size = 1 print (id(l1))
Q: What is the difference between
• l1 = [1, 2, 3, 4]
l2 = l1
l2[-1] = 5
print(l1)
• l3 = [1, 2, 3, 4]
l4 = l3[::]
l4[-1] = 5
print(l3)
• And why is that difference?
• Look at the definition of slicing: Slicing creates a new variable, made
of parts of another variable
Slicing (II) examples when start and/or end <0
new_list = existing_list[start:end:step_size]
• l1 = [1,2,3,4,5,6,7,8]
• print(l1[7]) # You ask for the eight element
# Onscreen: 8
• print(l1[-1]) # You ask for the last element
# Onscreen: 8
• Print(l1[-5:5])
# Onscreen: [4, 5]
• Print(l1[:-5])
# Onscreen: [1, 2, 3]
Slicing (III) with negative steps
l1 = [1,2,3,4,5,6,7,8]
While with positive steps you go from the start
index to the right, with a negative step you go to
the left.
• print(l1[5:1:-2]) # Onscreen: [6, 4]
• print(l1[5::-1]) # Onscreen: [6, 5, 4, 3, 2, 1]
• print(l1[:1:-1]) # Onscreen: [8, 7, 6, 5, 4, 3]
• print(l1[1:5:-2]) # Onscreen: []
Python will check whether you are already past the
end index, it works similar as:
• print(l1[5:1:2]) # Onscreen: []
Q: What will be the result of
L1 = [1, 2, 3, 4]
print(l1[::-1])
Answer:
[4, 3, 2, 1]
Slicing with strings and tuples
• Slicing can also be done with strings and tuples
• t1 = (1, 2, 3)
print(t1[1:]) # Onscreen: (2, 3)
• s1 = 'uva Amsterdam'
print(s1[5:-3:2]) # Onscreen: mtr
Changing a slice of a list
• Changing a list
l1 = [1, 2, 3, 4, 5, 6]
l1[1:4] = l1[1:4][::-1]
print(l1) # Onscreen: [3, 2, 1, 4, 5, 6]
• Tricky
l1 = [1, 2, 3, 4, 5, 6]
l1[1:2] = [1, 1]
print(l1) # Onscreen: [1, 1, 1, 3, 4, 5, 6]
• vs
l1 = [1, 2, 3, 4, 5, 6]
l1[1] = [1, 1]
print(l1) # Onscreen: [1, [1, 1], 3, 4, 5, 6]
Q: What will be the result of
l1 = [1, 2, 3, 4]
l1[::2] = [9] * 2
print(l1)
• Answer: [9, 2, 9, 4]
Changing the slice of a tuple or a string
• s1 = 'uva Amxterdam'
s1[6] = 's'
# Gives an error
• s1 = 'uva Amxterdam'
s1 = s1[:5] + 's' + s1[7:]
print(s1)
• t1 = (1, 4, 3)
t1[1] = 2
# Gives an error
• t1 = (1, 4, 3)
t1 = t1[:1] + (2,) + t1[2:]
print(t1)
Range
• range(start, stop, step)
• To generate a series of numbers. Start, stop, step work comparable with list
slicing, but as you will see the defaults work a bit different.
x = list(range(6))
print(x) # Onscreen: [0, 1, 2, 3, 4, 5]
x = list(range(3,6))
print(x) # Onscreen: [3, 4, 5]
x = list(range(3,6,2))
print(x) # Onscreen: [3, 5]
Set
• s1 = {1, 2, 2, 3}
print(s1)
• Q: How to get rid of doubles in s1 = [1, 2, 2, 3]
print(list(set(s1)))
Functions
• We often want to (re)use pieces of code
• Pieces of code can be wrapped into a function, given a name, and then re-used
by referencing the name
• We can pass input to a function, these values are called arguments
• Functions can create output, we say functions can return a value
def size(length, width):
return length * width
print(size (2,3))
• We will write our own functions from Week 3 onwards
• Python comes with a lot of built-in functions, we already saw:
id
len
type
• We don't much care how these built-in functions are written, we just want to know
what it does ( = how it turns inputs into outputs)
• Organizing your code into functions is a very good idea, but
Objects
• Organizing your code in functions is a good idea, but organizing your code
in objects may even be better
• Objects can encapsulate (≈ contain) functions and data
• Objects are always defined on the basis of a blueprint, and that blueprint is
called a class, so you first have to define the class:
class Rectangle:
def __init__(self, length, width):
self.length = length
self.width = width
def size(self):
return self.length * self.width
Objects
• And now you can define your objects:
rectangle_1 = Rectangle(2,3)
rectangle_2 = Rectangle(3,3)
print(rectangle_1.size(), rectangle_2.size())
In Python, everything is an object
• For example every variable is an object with a type, a value, and zero or more
names.
• Depending on the type a variable has several methods.
• Functions that are encapsulated in objects are called methods
• Methods can take arguments, and they also have access to the data inside
the object
• Sometimes, methods give us return values
• Other times, they just change the data inside the object
• Syntax: object.method_name(arguments)
• Example:
s1='UVA Amsterdam'
s1=s1.upper() or s1.upper() which is correct
print(s1) # Onscreen: UVA AMSTERDAM
• In Python if you want to use objects you have to define classes, but we don't do
that for variables. Conclusion for every datatype there is already a built-in class,
that defines what you can do with that variable of that type.
Importing additional functionality from
packages
• Python ecosystem = core language + standard library + third-party
packages
• The ecosystem is enormous, there is no way to make it available by
default
• That's why we need to install third-party packages separately, for
example
• Even the standard library is large; it's functionality must be imported
to be used. Eg import math
• Importing is about making the contents of a module (= Python file)
available in the namespace of our program
Example: how to access the randint function
in the random module of the numpy package
• print( numpy.random.randint(1, 10)) # error
• import numpy
print(numpy.random.randint(1, 10)) # works
• import numpy as np
print(np.random.randint(1, 10)) # works
print(numpy.random.randint(1, 10)) # error