University of Helsinki: Python Programming MOOC 2026
Learning from this course & Elegant Code
"Read the questions completely first. You always over-engineer when the questions are very simple.""
"DON'T TRY TO CRACK THE GAME OR THINK YOU ARE GOING TOO FAR IF YOU ARE THINKING IN A DIFFERENT WAY THAT INTENDED. SOLVE IT HOW YOU BEST THINK IS BEST.""
Split Strings into lists
def exam_and_exercise_completed(inpt):
space = inpt.find(" ")
exam = int(inpt[:space])
exercise = int(inpt[space+1:])
return [exam, exercise]
Better Boundary: Grading System
def grade(points):
boundary = [0, 15, 18, 21, 24, 28]
for i in range(5, -1, -1):
if points >= boundary[i]:
return i
Initialize a list with predefined length
grades = [0] * 6
Part 1
This course has reminded me how important recall is over recognition and the reason why many "video only lectures/courses" fail at it.
You feel you are getting something, sometimes smugly, and never get to practice them. And when it comes to actually trying to solve a problem you come up blank.
To be very clear, mooc.fi's Java hands on Java course(still incomplete BTW) was the reason I qualified for a job interview:
#TODO insert video here once moved
Part 2
- Statement is a part of the program which executes something.
- Block is a group of consecutive statements that are at the same level in the structure of the program.
- Expression is a bit of code that reulsts in a determined data type.
- Function executes some functionality, they also can take arguments/parameters.
- else branch is not mandatory especially when a lot of elif are involved. However, else incompasses all the conditions not accounted for so it's still a good check for outside expected cases.
- #TODO: ?: statement
- x>=a & x<=b can be rewritten as a<=x <=b , although not higely used as it's missing from other langauges
- The order of conditional statements especially involving loops is a common source of bugs. Debugging is often the simplest way to finding their cause.
PART 3
- Becoming a proficient progammer requires a lot of practice, sometimes even quite mechanical practice. It also involves developing problem solving skills and applying intuition.
- Some of the exercises in this course are not mandatory, you only need 25% of the points from each part to pass the course.
And the challenges might seem quite overwhelming.
But where's the fun in that? Frustration is welcome, that's the first thing I know about Computer Science, if you are not frustrated you are not pushing yourself enough.
- ni6hant - Move on from an exercise which feels difficult. You can always come back later, the difficulty spike isn't linear, it's all over the place.
- Loop: Initialisation, condition & update.
- Hardcode input values while debugging when trying to figure out a problem with the code
-
Indexing of String: 0 1 2 3 4 h e l l o Starts from 0 But also from the other end, it works like this: h e l l o -5 -4 -3 -2 -1 CAREFUL, IT'S FROM -1 AND NOT 0 IN THE OTHER DIRECTION
- Since string indexing begins at zero, the last character is at index len(input_string) - 1, not at len(input_string).
- There are situations where the program should prepare for errors caused by input from the user or other devs or other parts of the code, basically, the input.
-
Note: This no longer results in an error after Python 3.12 or PEP 701: Source
Using the same quote twice will return an error: print(f"{"#"*stringLength}") with which Python gets confused where the string starts and ends If you really wanted to use an f-string, you'd need different quotes: print(f'{"#" * stringLength}') -
print(f'"-"*{len(inputString)}') is incorrect as the entire expression should be inside the braces. print(f'{"-" * len(inputString)}') is correct or simply use, print(len(inputString) * "-") - Half open intervals:
Slicing is [a:b] which is NOT AS PER THE MATEMATICAL NOTATION. It's actually [a:b) as per matheamtical notation.
index at a is included but b is NOT
Note: If a is excluded, it defaults to 0 or the beginning of the string. And similarly if the end is excluded, it default to the total lenght of the string.
That's where the term "slice" comes from. - The in operator: Tells us if a string contains a particular string.
- The find method returns the first index where a searched string was found or a -1 if it was not found.
inputString.find("substringToFind")
Note: find method also returns -1 if the search string is longer than the main string - Methods work quite similarly to functions but methods are always attached to the object they are called on.
- More Loops:
continuejumps the execution to the beginning of the loop- In nested loops,
breakandcontinueonly effect the innermost loop they are part of. - Use Visualization Tool to understand nested loops which can get confusing really fast.
-
"Changing the input by adding an extra space or initializing it to something non-standard is a great way to get rid of exception cases.
I thought it wasn't."
- ni6hant
- 4. Defining functions
- Python treats all code that is not within
- On this course the automatic tests that are run on the exercise files require an empty main function. No commands should be left in the main function of your solution.
def greet(): print("Hi!") # Write your main function within a block like this: if __name__ == "__main__": greet() - Define a function by:
def function_name(): -
Argument is used with the data passed to the function.
Inside the function, the arguments are assigned to variables called Parameters. -
"" is a valid string object with length 0 and trying to access it's index 0 WILL RESULT IN AN ERROR.
Instead of using if len(text)>0: Simply use: if text:
- ni6hant - Don't use global variables inside functions accidentally instead of the local ones. These bugs are hard to trace.
-
/ always returns floating point division. // returns whole number division(floor division) % modulus and the reminder of the division.
PART 4
- 1. The Visual Studio Code editor, Python interpreter and built-in debugging tool
- Ctrl + C to stop a running code.
- Use python3 or python in Terminal of VSC to check small things.
Note: It will only print something out only if the line of code has a value.
No need to use print explicitly in interpreter.
Note: Remember to close the interpreter with Ctrl+Z or quit() or exit() otherwise other python programs will cause issues. - Browser based python interpreter
- Instead of searching online, use dir(object) to know which methods are available on this given object. At this stage, ignore the underline methods.
- 2. More functions
- Computer Science as a discipline does aim to be as exact a science as possible. Using well defined terminology helps.
- return statement ends the execution of the function immediately. You can use that to your advantage to cut the function early like a check or something.
- Pretty obvious but return values instead of printing them in the function.
- Use hints alongside function calls that specifies the type of argument for that function. And similarly one for return with ->
Note: These are just hints, not safeguards against type errors.def name(message : str, times : int): def ask_for_name() -> str: name = input("Mikä on nimesi? ") return name
- 3. Lists
- List: Collection of values which is accessed via a single variable name. The values in this list are called values or elements.
- Empty List Creation
my_list = [] - Items in a list are exactly the same way in a string.
- Unlike strings, list are mutable which means their contents can change.
-
The rest of the values shifts one forward.numbers.insert(value,indexPositionToInsert) -
Removing items from a list:
List now shortens. Pop also returns the removed item.my_list.pop(indexOfItemToRemove) my_list.remove(valueOfItemToRemove → First Occurrence only) in checks if there is an item in the list or not.
- sort sorts the list but sorted just returns a sorted list and doesn't modify the original list
max, min, sum- Lists can be accessed either via methods or functions:
- For the most part you will use methods with a dot operator:
my_list.append(1) - Some can take the whole list as an argument:
greatest = max(my_list)
- For the most part you will use methods with a dot operator:
- list can be used as argument and also return values:
def median(my_list: list): ordered = sorted(my_list) list_centre = len(ordered) // 2 return ordered[list_centre] - Most important function of a function is: they can help you divide code into smaller, easily understandable logic wholes.
-
Organising code into separate function makes it easier to handle logic wholes. You can also test various parts of the code works properly separate from each other.
Also, makes the code reusable. - Python Documentation on Lists
- 4. Definite iteration
whileloop is indefinite as the program doesn't know beforehand how many iterations the loop will perform. It will keep looping until the conditions become false, or the loop is broken out of.forloop: The number of iterations is determined when the loop is set up so it falls under definite iteration.
for <variable> in <collection>: <block>- The idea is that the for loop takes the items in the collection one by one and performs the same actions on each. The programmer doesn't have to worry about which item is being handled when.
- A for loop makes straightforward traversal through a collection of items very simple.
range(n): n is the end point of the range. And the range will go from 0 to n-1.range(a,b): again is not the mathematical notation but is [a,b) so a is included but b isn't. This range goes from a to b-1.range(start,endbefore,stepSize)stepSize is clear itself. Unless specified it's 1.- Use range along with for loops.
- You can also use 0 as false and other values as true
rangereturns a range object and not a list of object for you to print. uselist(range(a,b))to convert the range to a list.- A very common programming task is finding the best or worst item in a list, according to some criteria.
A simple solution is using a helper variable to "remember" which of the items processed so far was the most suitable, and then this temporary best choice is then compared to each item in turn. A rough draft if you please:best = initial_value # The initial value depends on the situation for item in my_list: if item is better than best: best = item # We now have the best one figured out!
- 5. Print statement formatting
- print using commas→ No need to format as string.
- Add
sep=""(separator) in the print parameters to remove extra spaces that are added by default when using commas with print()
Note: sep can be used to also use something else as separator. - Add
end=""to remove the new line from each print.
Note: Just as above. - Think of f-strings as functions which creates a normal string based on the arguments within the curly brackets.
- We can define the format which f-strings (Formatted String Literal) can have.
print(f"The number is {number:.2f}")for 2 decimal places. -
15 here means 15 characters are reserved for name. First they are justified to the left(default) then to the right.names = [ "Steve", "Jean", "Katherine", "Paul" ] for name in names: print(f"{name:15} centre {name:>15}")Steve centre Steve Jean centre Jean Katherine centre Katherine Paul centre Paul - You can use f-strings anywhere not just with print commands..
name = "Larry" age = 48 city = "Palo Alto" greeting = f"Hi {name}, you are {age} years of age" print(greeting + f", and you live in {city}")Hi Larry, you are 48 years of age, and you live in Palo Alto
- 6. More strings and lists
- Lists can be sliced just like strings
- The
[]works just like the range function which means we can also give it a step, for example:
Outputs:my_string = "exemplary" print(my_string[0:7:2]) my_list = [1,2,3,4,5,6,7,8] print(my_list[6:2:-1])eepa [7, 6, 5, 4]
-
If we omit indexes, the operator defaults to including everything. Among other things, you can write a very small program to reverse a string.
OutPutmy_string = input("Please type in a string: ") print(my_string[::-1])Please type in a string: exemplary yralpmexe - DON'T USE THE GLOBAL VARIABLE INSTEAD OF THE PARAMETER BY ACCIDENT:
def print_reversed(names: list): # using the global variable instead of the parameter by accident i = len(name_listnames) - 1 while i >= 0: print(name_list[i]) i -= 1 # here the global variable is assigned name_list = ["Steve", "Jean", "Katherine", "Paul"] print_reversed(name_list) print() print_reversed(["Huey", "Dewey", "Louie"]) - Strings are immutable(they can't be changed: assigned or sorted even).
- Strings are immutable but the variables holding them are not.
Whn lists' items are reassigned the contents of the referenced item in the list is changed, but when a string is concatenated, the whole reference is changed to a new string. countmethod counts the number of specified item or substring that occurs in the target. Works with both strings and lists.
Note: count method won't count overlapping occurrences. In the stringaaaathe method counts only two occurrences of the substringaaeven though there would actually be three if overlapping occurrences were allowed.-
replacemethod creates a new string, where a specified substring is replaced with another string.
Note: It will replace ALL occurrences of the substring.
Pretty common error: Forgetting that strings are immutable.
my_string = "Python is fun" # Replaces the substring but doesn't store the result... my_string.replace("Python", "Java") print(my_string) - Python string method
isupper()returnsTrueif a string consists of only uppercase characters. abs(a-b)is absolute or modulus operator- Rule 1 of programming projects: Not try to solve everything at once.
The program should be built out of smaller sections, such as helper functions.
Verify functions of each parts before moving onto the next.
If you try to handle too much at once, chaos ensues. -
To test functions outside of main function, you can:
defining the main function explicity. A single function call is then easy to comment out for testing.# helper function for determining the grade based on the amount of points def grade(points): # more code def main(): all_points = [] # your program code goes here # comment out the main function #main() # test the helper function student_points = 35 result = grade(student_points) print(result) - When passing values between functions, you can save the data in the main function which has global scope.
- Why Global state is evil. If functions are able to change a global variable, unexpected things may start happening in the program, especially when the number of functions grows large.
- Passing data into and out of functions is best handled by arguments and return values.
PART 5
- 1. More lists
PART 6
1. Reading files 2. Writing files 3. Handling errors 4. Local and global variables
PART 7
1. Modules 2. Randomness 3. Times and dates 4. Data processing 5. Creating your own modules 6. More Python features
PART 8
1. Objects and methods 2. Classes and objects 3. Defining classes 4. Defining methods 5. More examples of classes
PART 9
1. Objects and references 2. Objects as attributes 3. Encapsulation 4. Scope of methods 5. Class attributes 6. More examples with classes
PART 10
1. Class hierarchies 2. Access modifiers 3. Object oriented programming techniques 4. Developing a larger application
PART 11
1. List comprehensions 2. More comprehensions 3. Recursion 4. More recursion examples
PART 12
1. Functions as arguments 2. Generators 3. Functional programming 4. Regular expressions
PART 13
1. Pygame 2. Animation 3. Events 4. More pygame techniques
PART 14
1. Game project 2. Robot and boxes 3. Finishing the game 4. Your own game