Termbank
  1. A
    1. Absolute Path
    2. Ajonaikainen
      concepts
    3. Alustaminen
      variables values
    4. Argumentti
      values functions
    5. Arvo
      values
    6. Assignment
      variables values
    7. Assignment Operator
      variables values operators
    8. Attribute
      objects
    9. Attribuutti
      Attribute
    10. Avainsana
      names
    11. Aliohjelma
      Function
  2. B
    1. Boolean
      control flow
    2. Boolean Operator
      control flow operators
    3. Boolen operaattori
      Boolean Operator
    4. Branch
      try structures conditional structures
    5. Bug
      problem solving
    6. Bugi
      Bug
    7. Builtin Function
      functions
    8. Block
      Code Block
    9. break
      loops keywords
  3. C
    1. Callback
      functions
    2. Carriage Return
      escaping strings files windows
    3. Code Block
      control flow functions
    4. Code File
      concepts
    5. Command Line Argument
      terminal
    6. Comparison Operator
      control flow operators
    7. Comparison Value
    8. Condition
      control flow
    9. Conditional Statement
      control flow
    10. Conditional Structure
      conditional structures control flow
    11. Constant
      variables values
    12. Control Structure
      try structures loops conditional structures
    13. Call
      Function Call
    14. Ctrl + C
      Näppäimistökeskeytys
    15. Code
      Source Code
    16. Callback
      Takaisinkutsu
    17. Command Prompt
      Terminal
    18. continue
      loops keywords
  4. D
    1. Data
    2. Data Format
      strings files
    3. Data Structure
      dictionaries concepts lists
    4. Debugging
    5. Default Value
      values functions parameters
    6. Dictionary
      data structures
    7. Docstring
      documentation
  5. E
    1. Epätosi
      values
    2. Error Message
      problem solving
    3. Escape
      strings
    4. Evaluointi
      expressions values
    5. Event
      concepts
    6. Exception
      try structures problem solving
    7. Exception class
      exceptions control flow
    8. Execution
      expressions concepts
    9. Element
      Item
    10. enumerate
      lists loops
  6. F
    1. False
      Epätosi
    2. File Extension
      files
    3. File Handle
      objects files
    4. Filename
      strings files
    5. Float
      values types
    6. Format
      strings printing
    7. Formatting
      Format
    8. Function
      functions
    9. Function Call
      functions statements
    10. Function Definition
    11. f string
      strings
    12. for
  7. G
    1. Generator
      objects loops
    2. Globaali muuttuja
      variables values
    3. Global Scope
  8. H
    1. Handle
      File Handle
    2. Handler
      functions concepts
    3. Hyppy
      control flow
    4. Hardkoodaus
      Kovakoodaus
  9. I
    1. if statement
      Conditional Statement
    2. if structure
      Conditional Structure
    3. Identifier
      variables functions
    4. Indentation
      concepts
    5. Index
      values lists
    6. Index Subscription
      values lists
    7. Infinite Loop
      loops
    8. Input
      strings concepts
    9. Interface
      modules functions concepts
    10. Item
      values lists
    11. Iteration
      loops
    12. import
      modules
  10. K
    1. Key
      dictionaries values
    2. Keyword Argument
      functions
    3. Kirjasto
      modules
    4. Kommentti
      debugging documentation
    5. Kovakoodaus
      values
    6. Käyttöliittymäelementti
    7. KeyboardInterrupt
      Näppäimistökeskeytys
  11. L
    1. Lause
      concepts
    2. Lauseke
      concepts
    3. List
    4. Literal
      values
    5. Local Variable
    6. Loop
      control flow
    7. Loop Variable
      variables loops
  12. M
    1. Main Program
      concepts
    2. Merkki
    3. Merkkijono
      values types
    4. Method
      functions objects
    5. Member Function
      Method
    6. Method Call
      expressions objects
    7. Module
    8. Mutable
      values concepts lists
    9. Muuntumaton
      values strings concepts
    10. Määrittely
      concepts
  13. N
    1. Name Conflict
    2. Namespace
      modules functions concepts
    3. Newline
      strings files
    4. Nimeämätön vakio
      values constants
    5. Näppäimistökeskeytys
      exceptions
  14. O
    1. Objekti
      concepts
    2. Olio
      Objekti
    3. Ohjelmointityyli
    4. Ominaisuus
      objects
    5. Opening Mode
      files
    6. Operand
    7. Operation
      expressions
    8. Operator
    9. Optional Argument
      values functions parameters
  15. P
    1. Parameter
      functions
    2. Parametrization
    3. Path
    4. Placeholder
      strings printing
    5. Poikkeusten käsittely
      control flow exceptions
    6. Precedence
      expressions concepts
    7. Presedenssi
      Precedence
    8. Precedence
    9. Printing
      strings concepts
    10. Programming Problem
      problem solving
    11. Python Console
      tools
    12. Python Interpreter
      tools
  16. R
    1. Running
      Execution
    2. Recursion
      functions concepts
    3. Referring
      variables values objects
    4. Relative Path
    5. Return
      values functions
    6. Return Value
  17. S
    1. Silmukka
      Loop
    2. Suoritusjärjestys
      Precedence
    3. Sapluuna
      strings concepts
    4. Scope
      concepts blocks
    5. Separator
      strings files lists input
    6. Sequence
      data structures concepts loops
    7. Slicing
      lists
    8. Solution Model
      problem solving
    9. Source Code
      concepts
    10. State
      concepts
    11. Stub
      problem solving functions
    12. Syntax
      concepts
    13. Syntax Error
      exceptions
    14. Shell
      Terminal
    15. Stacktrace
      Traceback
  18. T
    1. Taikaluku
      Nimeämätön vakio
    2. try-rakenne
      Poikkeusten käsittely
    3. Takaisinkutsu
      functions
    4. Terminal
      tools
    5. Testaaminen
      problem solving concepts
    6. Text File
      files
    7. Tosi
      values
    8. True
      Tosi
    9. Traceback
      problem solving
    10. Tuple
      data structures lists
    11. Type Conversion
      values functions types
    12. Tyylisääntö
    13. Tyyppi
      values concepts
  19. U
    1. User Interface
      concepts
  20. V
    1. Variable
      values concepts
  21. W
    1. while
      loops
    2. with
      files
Completed: / exercises

4. Exercises: Modules of the End Times

These are the last exercises of the course. Think about that! But preferably only after you've thought about the exercises themselves. The topics today cover files and Python modules. The project-related exercises also offer quite fat chunks of code for the couse project.

Learning Goals

After this exercise you should be somewhat familiar with manipulating files. You'll also know quite a more bit about using modules, and also know how to make your own code work as a module. You'll also become familiar with the libary (or libraries) designed for the course project.

Example

As we promised in the material, this example covers the sweeperlib
library
that was made specifically for the course project. The example mostly covers how
handlers
behave with this library. It also continues from a couple of exercises in the sense that we're finally showing you how to implement movement using unit vectors.
Running the example requires Pyglet, which can be installed with
pip install pyglet
If the example does not work after this and you get any kind of GLException, install an older version of Pyglet:
pip install "pyglet<2.0.0"

Task Description

It would be fun to make an entire game prototype but that would involve a lot of things that are not necessary for this course. Instead, we're just going to make a simple, controllable game object. Let's set our goal to making a character that moves on its own and is animated, and it changes its direction when the player clicks somewhere on the screen. Let's also say that the character's movement speed isn't fixed, but instead accelerates upward from zero whenever the target point changes.

Solution

sweeperlib.py
The very first thing is to make something show up on the screen. This is where sweeperlib comes in to help. Its core principles are pretty much the same as the library we described in the material: the program's main loop runs Somewhere Else (tm), and the game logic itself is implemented in handler functions. This time around we just don't have interface components to attach our handlers to. If we take a look at sweeperlib, it can attach handlers of four types:
At minimum a game needs to have a draw handler in order for anything to be shown on the screen. Whereas our guilib did the drawing for us, this time we need to do it ourselves. This is because sweeperlib doesn't define premade game objects the same way guilib defines user interface components. The main responsibility of the draw handler is to draw each game object to a position on the screen tht matches its position in the game's logic. However, before we can actually draw anything we need to load some graphics. This step is not needed in minestomping because the library already contains a function to load the sprites that we've provided. Likewise there is no need to import pyglet in your own program, and specifically in this page's exercises you are not allowed to do that. For this example we need to create a separate function for loading two sprites (from the zip below) from the given
path
.
cross.zip
import pyglet
import sweeperlib

WIDTH = 800
HEIGHT = 600

def load_sprites(path):
    pyglet.resource.path = [path]
    sprites = {
        "0": pyglet.resource.image("plus_1.png"),
        "1": pyglet.resource.image("plus_2.png")
    }
    sweeperlib.graphics["images"] = sprites
We didn't choose the sprite
keys
arbitrarily - the reason will be revealed later. We also need the actual draw handler, which we'll implement by following the example at the end of sweeperlib - the whole process has been described in detail in the library's
docstrings
. We'll draw our sprite to 100, 100.
def draw_game():
    sweeperlib.clear_window()
    sweeperlib.draw_background()
    sweeperlib.begin_sprite_draw()
    sweeperlib.prepare_sprite("0", 100, 100)
    sweeperlib.draw_sprites()
When these two functions are used in initializing the game and in the main program, we can see a prett plus sign on the screen. The handlers aren't attached to interface elements this time. Instead they're attached directly to the library itself by functions that exist for this purpose.
def start_game():
    sweeperlib.create_window(WIDTH, HEIGHT)
    sweeperlib.set_draw_handler(draw_game)
    sweeperlib.start()
    
if __name__ == "__main__":
    load_sprites("sprites")
    start_game()
The next step is to create some interactivity. We can start by making the game recognize the user's clicks, and react to them by teleporing the character to the spot. At this point we'll employ a familiar
dictionary
. As
handlers
still have the same issue we uncovered in the material, we cannot influence what arguments they receive. In other words, just like in the material, the game's state should be put into a
global
dictionary. We'll call it state, and place the dictionary that represents our character inside it with the "player"
key
.
state = {
    "player": {
        "x": 0,
        "y": 0,
        "heading": 0,
        "speed": 0
    }
}
The dictionary contains empty values of the correct type for each key. Once again the purpose is to show at a glance what attributes the game's characters have. Setting the values (to random position) is done in a separate create_player function.
def create_player():
    state["player"] = {
        "x": random.randint(0, WIDTH - 1),
        "y": random.randint(0, HEIGHT - 1),
        "heading": 0,
        "speed": 0
    }
Now that we have an object that has a position in the game logic, we can make a mouse handler that changes the position. The handler has four
parameters
although we only need the first two for x and y coordinates. The idea is the same as before: the handler changes values of the dictionary attached to the "player" key in the state dictionary. This makes the changes take effect everywhere this dictionary is used.
def handle_mouse(x, y, button, modifiers):
    state["player"]["x"] = x
    state["player"]["y"] = y
We also need to change the draw handler to draw the character where it actually is:
def draw_game():
    sweeperlib.clear_window()
    sweeperlib.draw_background()
    sweeperlib.begin_sprite_draw()
    sweeperlib.prepare_sprite("0", state["player"]["x"], state["player"]["y"])
    sweeperlib.draw_sprites()
And finally use the new functions when starting the game:
def start_game():
    create_player()
    sweeperlib.create_window(WIDTH, HEIGHT)
    sweeperlib.set_draw_handler(draw_game)
    sweeperlib.set_mouse_handler(handle_mouse)
    sweeperlib.start()
Basically this is enough information you need about handlers to implement a minesweeper. Majority of the game's logic will happen in handlers, and the functions they call. That said, this example doesn't quite yet match the specification, so we'll work on it a bit more. We wanted the character to accelerate towards the chosen point instead of teleporting to it. Because the character already has speed and heading, we need a click handler that changes the heading and sets the speed to zero. We also need to add acceleration as one attribute of the character.
The mouse handler becomes:
def handle_mouse(x, y, button, modifiers):
    set_heading(state["player"], x, y)
    state["player"]["speed"] = 0
Setting the heading is best done in its own funcion because it sounds like something that would be useful in more than just this one context. There might even be more than one object in the game in the future! At this point we need to recall some basic trigonometry: if we know the base and height of a triangle, the angle is obtained with arctan, which has its own function in the math module. We just need to know that atan isn't good enough because it doesn't handle the signs of x and y separately - atan2 does.
def set_heading(character, target_x, target_y):
    distance_x = target_x - character["x"]
    distance_y = target_y - character["y"]
    character["heading"] = math.degrees(math.atan2(distance_y, distance_x))
We don't have any real reason to convert angles to degrees here since they're never shown to players. We just did so because it makes the code a bit easier to digest. Especially if the program needs to be debugged at some point, and we need to investigate the headings of objects, degrees come in handy. Anyway, the player can now control the character. It just doesn't quite move yet. For this we need a third handler, one that updates the game state continuously, or approximately 60 times per second. The documentation of sweeperlib tells us that such a handler receives one argument: time elapsed since the last time it was called.
def update_game(elapsed):
    state["player"]["speed"] += state["player"]["accel"]
    update_position(state["player"])
You can find the update_position function called here from your own exercise solution. This solution relies on the game actually achieving 60 frames per second. If the game didn't achieve this, the game logic would slow down. A more correct solution would be to use the function's parameter so that all time-dependent values are multiplied by elapsed * 60 (which is exactly 1 if the game runs at 60 fps). We'll leave the code as is however, because it's a bit easier to read. When this handler is registered in the start_game function, we've achieved a controllable object.
def start_game():
    create_player()
    sweeperlib.create_window(WIDTH, HEIGHT)
    sweeperlib.set_draw_handler(draw_game)
    sweeperlib.set_mouse_handler(handle_mouse)
    sweeperlib.set_interval_handler(update_game)
    sweeperlib.start()
As a last curiosity, we'll show you how to do a two-frame animation. In order to do this, we need to add another key to the character dictionary. The value of this key indicates which sprite is shown currently. The keys for the sprites were "0" and "1" when we loaded them. In other words this key will always be inside [0, 2). We also need a constant to adjust the animation speed - a picture blinking 60 times per second is not pleasant to look at. With a value of 0.1 the sprite only changes 6 times per second.
ANIM_SPEED = 0.1

state = {
    "player": {
        "x": 0,
        "y": 0,
        "heading": 0,
        "speed": 0,
        "accel": 0,
        "sprite": 0
    }
}
Because we had the foresight to name the sprites "0" and "1" we can do the swapping with mathemagics. This is added to the update_game function. At each update the value of the sprite key is incremented by the animation speed constant, so that it takes 10 cycles from zero to one, and another 10 from one to two. Because there is no sprite number 2, we can wrap the cycling around to zero with modulo 2.
def update_game(elapsed):
    state["player"]["speed"] += state["player"]["accel"]
    state["player"]["sprite"] = (state["player"]["sprite"] + ANIM_SPEED) % 2
    update_position(state["player"])
Again our game would be more stable if we multiplied the animation speed by elapsed * 60. The drawing handler also needs a change where it picks the sprite to draw from the dictionary. Because the value is a float from range [0, 2), it needs to be converted to an integer. The keys in the graphics dictionary are
strings
, but we peek inside the library it converts the sprite argument to a string - so we can give it integers. With this we've created a beautiful(?) animation. You can gaze at the result in amazement by downloading the program.
crossgame.py
import math
import random
import pyglet
import sweeperlib

WIDTH = 800
HEIGHT = 600
ANIM_SPEED = 0.1

state = {
    "player": {
        "x": 40,
        "y": 40,
        "heading": 0,
        "speed": 0,
        "accel": 0,
        "sprite": 0
    }
}

def load_sprites(path):
    pyglet.resource.path = [path]
    sprites = {
        "0": pyglet.resource.image("plus_1.png"),
        "1": pyglet.resource.image("plus_2.png")
    }
    sweeperlib.graphics["images"] = sprites
    
def create_player():
    state["player"] = {
        "x": random.randint(0, WIDTH - 1),
        "y": random.randint(0, HEIGHT - 1),
        "heading": 0,
        "speed": 0,
        "accel": 0.2,
        "sprite": 0
    }

def convert_to_xy(a, r):
    x = int(round(math.cos(a) * r))
    y = int(round(math.sin(a) * r))
    return x, y    
    
def set_heading(character, target_x, target_y):
    distance_x = target_x - character["x"]
    distance_y = target_y - character["y"]
    character["heading"] = math.degrees(math.atan2(distance_y, distance_x))
    
def update_position(char):
    dx, dy = convert_to_xy(math.radians(char["heading"]), char["speed"])
    char["x"] += dx
    char["y"] += dy

def handle_mouse(x, y, button, modifiers):
    set_heading(state["player"], x, y)
    state["player"]["speed"] = 0
    print(state["player"])

def update_game(elapsed):
    state["player"]["speed"] += state["player"]["accel"]
    state["player"]["sprite"] = (state["player"]["sprite"] + ANIM_SPEED) % 2
    update_position(state["player"])
    
def draw_game():
    sweeperlib.clear_window()
    sweeperlib.draw_background()
    sweeperlib.begin_sprite_draw()
    sweeperlib.prepare_sprite(int(state["player"]["sprite"]), state["player"]["x"], state["player"]["y"])
    sweeperlib.draw_sprites()
    
def start_game():
    create_player()
    sweeperlib.create_window(WIDTH, HEIGHT)
    sweeperlib.set_draw_handler(draw_game)
    sweeperlib.set_mouse_handler(handle_mouse)
    sweeperlib.set_interval_handler(update_game)
    sweeperlib.start()
    
if __name__ == "__main__":
    load_sprites("sprites")
    start_game()

Common Exercises

As usual everyone needs to do these

Warmup Exercise

Spiraling Out of a File

This exercise continues the development of our a-spiraling code from last exercises. A new feature is to be added: it can draw by reading instructions from a file that contains multiple spirals. Each line in the file has the parameters of one spiral.
Learning goals: Reading from files, and converting file contents to variables.
Goal: A program that reads drawing instructions from a file and uses them along with the existing draw function to draw spirals.

Introduction:
You'll need to draw_spiral function from last week's spiral exercise. Copy it to your code file.

Function specification: draw_from_file
  • Parameters
    :
    • filename to read (string)
The function must open a
file
and read its lines that describe spirals. Each line has values in the same order as the draw_spiral function's parameters separated by commas:
  • spiral's color (color value - either a color name or a hexadecimal color code)
  • number of arcs to draw (integer)
  • spiral's initial radius (integer)
  • radius growth (float)
  • pen weight (integer)
The function needs to read these values from each line, convert them to correct types, and then call the draw_spiral function with them. Although pen weight is an optional argument, it is found on every line in the file - you can safely assume that each line will have 5 values.
In general you can freely assume that there are no errors in the file.

Use Examples:
Below is one example of a file that your function should be able to read. There's also a familiar picture that's been drawn based on this file.
spiral.txt
black,20,10,3,1
red,10,20,4,3
blue,10,-20,-4,3

farmiliar picture, drawn in a new way
Warning: You have not logged in. You cannot answer.

Main Exercises

Dunkin' Donkeygotchi

Some might still remember Tamagotchis or other virtual pets from way past. In this exercise you will implement your own virtual pet - a virtual donkey, of course.
This exercise teaches you how to work with a program made of more than one file, and with code made by someone else. We've included some of the donkeygotchi's modules. Your task is to finish the job by filling gaps in the main program and by creating the user interface module. The internal logic of the bit donkey has been already defined, along with a bunch of constants.
Learning goals: Reading code written by other people and completing it. Implementing your own
modules
. Using
dictionaries
and
constants
in code.
Goal: Make a user interface module for an otherwise functioning donkeygotchi.

Introduction:
This exercise uses two completed
code files
and one half-finished file. The files have the following roles:
  • main.py: Main program module, functions as the program's "entrance" and implements the main loop that glues the program's logic together. This file has some placeholders marked with question marks that you have to fill in.
  • donkeydefs.py: Contains predefined
    constants
    (like Python's math.pi) that can be used in other modules of the program.
  • donkeylogic.py: The engine of the program that creates and manages data.
The code files can be found at the end under "Resources"

Unfinished Module: main.py
The program cannot be ran before the placeholders in main.py have been filled in. What you need to do for each can be found out by looking at the donkeylogic and donkeydefs modules.

Module Specification: donkeyinterface.py
  • Docstring
    :
    • "Defines the donkeygothi's user interface."
  • Functions
    :
    • show_state: (details below)
    • prompt_choice: (details below)
1st function specification: show_state
  • Parameters
    :
    • donkey's state in a data structure (dictionary)
This function prints the donkey's state, i.e. the values of age, money, satiation, happiness and energy. In addition, if the donkey has retired, a separate print is done to indicate this. The exact strings to use can be found from the examples at the end.
2nd function specification: prompt_choice
  • Parameters
    :
    • donkey's state in a data structure (dictionary)
  • Returns
    :
    • a valid input made by the user (string)
The function prints the available choices - based on the donkey's state - once, and then proceeds to prompt the user to make a choice until they give an input that is currently valid. If the donkey is not retired, the valid inputs can be found from the CHOICES list in the donkeydefs module; if the donkey is retired, valid inputs are in the RETIRED_CHOICES list. These constants should be used for both printing the available choices, and validating inputs. All strings to use in prompts and prints can be found from the examples.

Use Examples:
The donkey is 96 years old and has 0 eur.
Satiation: 5
Happiness: 5
Energy: 5
Choices: q, f, w, t
Input next choice: q
The donkey is 96 years old and has 0 eur.
Satiation: 5
Happiness: 5
Energy: 5
Choices: q, f, w, t
Input next choice: Z
Invalid input!
Input next choice: ???
Invalid input!
Input next choice: w
The donkey is 97 years old and has 1 eur.
Satiation: 5
Happiness: 5
Energy: 5
Choices: q, f, w, t
Input next choice: 
The donkey is 100 years old and has 12 eur.
Satiation: 6
Happiness: 9
Energy: 2
The donkey has retired.
Choices: q, r
Input next choice: X
Invalid input!
Input next choice: f
Invalid input!
Input next choice: t
Invalid input!
Input next choice: r
The donkey is 0 years old and has 0 eur.
Satiation: 5
Happiness: 5
Energy: 5
Choices: q, f, w, t
Input next choice: 

Resources:
Download these files from below.
donkeylogic.py
"""
Defines the donkeygotchi's internal logic
"""
import donkeydefs as defs

def init():
    """
    Initializes donkey data by creating a new dictionary with initial values for
    all keys, and returns it.
    """
    donkeydata = {
        "SATIATION": defs.INITIAL,
        "HAPPINESS": defs.INITIAL,
        "ENERGY": defs.INITIAL,
        "AGE": 0,
        "MONEY": 0,
        "RETIRED": False,
    }
    return donkeydata

def _age(donkeydata):
    """
    Ages the donkey and - if needed - puts it in retirement. Meant only for 
    internal use in this module.
    """
    donkeydata["AGE"] += 1
    
    if donkeydata["AGE"] == defs.RETIREMENT_AGE:
        donkeydata["RETIRED"] = True

def _update_states(donkeydata):
    """
    Changes the donkey's state as time passes, and puts the donkey in retirement
    if needed. Meant only for internal use in this module.
    """
    if donkeydata["AGE"] % 2 == 0:
        if donkeydata["SATIATION"] > 6 and donkeydata["ENERGY"] < defs.MAX_STATE:
            donkeydata["ENERGY"] += 1
        donkeydata["SATIATION"] -= 1
    if donkeydata["AGE"] % 3 == 0:
        donkeydata["HAPPINESS"] -= 1
    
    if donkeydata["SATIATION"] <= 0 or donkeydata["HAPPINESS"] <= 0 or donkeydata["ENERGY"] <= 0:
        donkeydata["RETIRED"] = True

def feed(donkeydata):
    """
    Feeds the donkey, i.e. raises its satiation, if it isn't at the maximum yet.
    """
    _age(donkeydata)
    _update_states(donkeydata)
    if donkeydata["SATIATION"] < defs.MAX_STATE:
        donkeydata["SATIATION"] += 1
    
def tickle(donkeydata):
    """
    Tickles the donkey, i.e. raises its happiness, it it isn't at the maximum yet.
    """
    _age(donkeydata)
    _update_states(donkeydata)
    if donkeydata["HAPPINESS"] < defs.MAX_STATE:
        donkeydata["HAPPINESS"] += 1

def work(donkeydata):
    """
    Makes the donkey work by spending its energy in return for money.
    """
    _age(donkeydata)
    donkeydata["ENERGY"] -= 1
    donkeydata["MONEY"] += 1
    _update_states(donkeydata)

donkeydefs.py
"""
Defines the variables that are used in the donkeygotchi.
"""

# input choices
QUIT = "q"
FEED = "f"
TICKLE = "t"
WORK = "w"
CHOICES = [QUIT, FEED, TICKLE, WORK]

RESET = "r"
RETIREMENT_CHOICES = [QUIT, RESET]

# Aasin tilat
INITIAL = 5
RETIREMENT_AGE = 100
MAX_STATE = 10

main.py
import ???
import ???
import ???

def main():
    """
    Creates a new donkey and implements the main menu logic of donkeygotchi.
    """

    donkeydata = donkeylogic.???
    
    while True:
        donkeyinterface.show_state(donkeydata)
        choice = donkeyinterface.prompt_choice(donkeydata)
        
        if choice == donkeydefs.QUIT:
            break

        if choice == donkeydefs.FEED:
            ???
        elif choice ==  donkeydefs.TICKLE:
            ???
        elif choice == donkeydefs.WORK:
            ???
        elif choice == donkeydefs.RESET:
            ???

if __name__ == "__main__":
    ???

return donkeyinterface.py and main.py. You can choose more than one file in the browser's upload dialog by pressing Ctrl down when choosing.
Warning: You have not logged in. You cannot answer.

Course Project Exercises 1

Choose one of these. These tasks are not required for minimal course completion.

Mine Assignment: Time to Mousey

Who would play a text-based terminal minesweeper in the 2000s? This exercise along with the following ones give you a basis that allows you to implement a beautiful Minestomper with real graphics and mouse controls. We've given you a custom library for this purpose, and this exercise starts your journey in getting familiar with it. The topics are application windows and handler functions.
Learning goals: Creating a window. Handling the mouse with sweeperlib. Implementing and using a handler function.
Goal: A program where the mouse handler tells where inside the window mouse was clicked.

Introduction:
This exercise uses the library we made for the Minestomper course project. It helps rather significantly in implementing a graphical interface. Download the library if you don't have it yet and explore it carefully. The library comes with rather extensive docstrings and a short example at the end.
sweeperlib.py
The Minestomper project page also contains some explanations about how to use the library - definitely worth a read at this point. You should also install Pyglet if you haven't already. Furthermore, if you get any kind of GLException when running the code, try to install an older version by typing
pip install "pyglet<2.0.0"
Note that in order to complete this exercise your code does not need to import Pyglet - all interaction with Pyglet is done through sweeperlib. The checking server doesn' even have Pyglet so trying to import in your code causes a ModuleNotFoundError exception. In the course project itself you can do what you want however.

1st Function Specification: handle_mouse
  • Docstring
    :
"""
This function is called when a mouse button is clicked inside the game window.
Prints the position and clicked button of the mouse to the terminal.
"""
  • Parameters
    :
    • x coordinate of the mouse (integer)
    • y coordinate of the mouse (integer)
    • mouse button (integer)
    • pressed modifier keys (integer - not used in this exercise but needs to be defined in order for the function to be callable)
The function prints its parameers to the terminal (see examples for formatting). The mouse button is an integer where each value corresponds to a different button. You don't need to memorize these values because you can use the sweeperlib constants MOUSE_LEFT, MOUSE_MIDDLE, and MOUSE_RIGHT to know which button was clicked. You can practice dictionaries by making one where these constants are the
keys
and strings "left", "middle", and "right" are their values.

2nd Function Specification: main
  • Docstring:
"""
Creates a game window and sets a handler for mouse clicks.
Starts the game.
"""
The main function has to create a window using the sweeperlib's create_window function, and set a mouse handler using the set_mouse_handler function. Study how these functions work. You can choose the size of the window freely. Background color doesn't matter because the window is not drawn after being created. At the end the application needs to be started with the start function.

Function Testing:
if __name__ == "__main__":
    main()

Use Examples:
These examples only show what is printed to the terminal.
The left mouse button was pressed at 123, 53
The right mouse button was pressed at 20, 10
The middle mouse button was pressed at 250, 39
Return the file you created, no other files.
Warning: You have not logged in. You cannot answer.

Spectral Assignment: Just an Ordinary Window

In order to see spectrums you need to learn the basics of graphical user interfaces. This is the first exercise in the series. It will teach you how to create a basic interface with a couple of components. A small library will assist you in this quest, allowing you to survive with a few simple function calls.
Learning goals: The basics of creating a use interface window. The basics of the guilib library used in the course project.
Goal: A program that creates an interface window.

Installation: matplotlib
The guilib module requires matplotlib in order to work. You can install it with the pip program by giving this command: pip install matplotlib. Pip is usually included with Python. See pre-exercises if you don't remember how to use it. In some Linuxes and in Mac OS X the command can be pip3 - pip alone installs for Python 2.

Introduction:
The exercises uses the guilib module that is also used in Spectral Matters. The library contains functions that allow you to create simple user interfaces. Download the library from the link below and study it carefully. It contains extensive docstrings and an example program at the end.
guilib.py
The first thing you should do is to test the library by running it. If you get a message about a missing DLL, it's very likely this one and you need to install it.
The course project page also gives a short introduction to graphical user interfaces. Should be a worthy read at this point.
Note that you do not need to import either Tkinter or Matplotlib into your own program - everything happens through guilib. These haven't been even installed on the checking server which means you will get ModuleNotFoundError exceptions if you try to return code that imports them.
Finally, create this dictionary into your program, it will contain references to the UI components.
widgets = {
    "textbox": None
}
Because the program is mostly based on handler functions you have no control over what parameters they can have. Therefore the program's state and references to components must be kept
globally available
. The best way to manage that is to collect everything into a dictionary that can be accessed from all functions.

1st Function Specification: print_testline
  • Docstring
    :
"""
Prints a test line into a textbox in the user interface.
"""
When the function is called it writes e.g. "donkeyswings" (doesn't matter, write what you want) to a textbox in the widgets dictionary. Use the library's write_to_textbox function. The message contents don't matter, its purpose is to just show that the UI components have been connected to each correctly.

2nd Function Specification: main
  • Docstring:
"""
Creates an application window with two buttons on the left and one textbox on
the right. Text can be printed to the box by pressing a button.
"""
The task of the main function is to create the interface components, connect handlers to buttons, and finally start the program. We want a window with two frames: on the left there should be two buttons, and on the right a textbox. The first button should be connected to the print_testline function we just created. The second button's handler is the library's quit function. You can choose the text on the buttons.
When you create the textbox, assign it to the previously defined dictionary.
You need the create_window, create_frame, create_button, and create_textbox functions from the guilib. The examples section shows a screenshot of the completed interface. Exact measurements might differ from your version but the layout must match.

Function Testing:
if __name__ == "__main__":
    main()

Use Examples:
The layout should look like this. Exact measurements can differ.
Warning: You have not logged in. You cannot answer.

Cutting Assignment: Rectangular Drawing

According to rumors the image cutter project requires use of rectangular inidicators to visualize cutting parameters. So, you probably need to learn how to draw them. Let's get to it then. We have a comfy little helper library to assist you.
Learning goals: Creating an application window and drawing a rectangle to it.
Goal: A program that opens an application window and draws a rectangle.

Introduction:
To start things off you will need the helper library, sweeperlib. If you didn't download it for trying out the
example at the beginning of this exercise page, now's the time to do so. Despite its name, the library is perfectly suited for this project topic too.
sweeperlib.py
Furthermore, your drawing function will need a rectangle to draw from somewhere. We are going to manage this by defining a main program level dictionary from which the rectangle parameters can be read from. Like this:
parameters = {
    "x": 0,
    "y": 0,
    "width": 100,
    "height": 100,
    "color": (10, 10, 255, 255),
}

1st Function Specification: draw
  • Docstring
    :
"""
Draws a rectangle based on the values in the parameters dictionary.
"""

This function doesn't have any parameters or return values. Open sweeperlib.py and read the docstring of set_draw_handler to learn how to implement a draw [!term=Handler!]handler[!term!]. In this task you need to draw the background, and a rectangle. The arguments for drawing the latter one must be read from the dictionary. The checker will write new values into this dictionary when calling your function. 

--

'''2nd Function Specification:''' {{{main}}}

* Docstring:

{{{highlight=python3
"""
Creates an application window and sets a handler for drawing rectangles.
Starts the application.
"""
The main function has to create a window using the sweeperlib's create_window function, and set a draw handler using the set_draw_handler function. Study how these functions work. You can choose the size of the window freely. At the end the application needs to be started with the start function.

Function Testing:
if __name__ == "__main__":
    main()

Allowed filenames: *.py

Warning: You have not logged in. You cannot answer.

Duck Assignment: Basics of Box Dragging

In order for us to be able to slingshot ducks into the air, the player needs to be able to drag the imaginary string of sling. This assignment introduces the required basics: how dragging things with the mouse works in general. This functionality will be offered by the support library made for this course.
Learning goals: Creating an application window. Dragging on object inside the window.
Goal: Program where the user can drag a box.

Introduction:
In order for
handlers
to conveniently access the box, it should be presented as a
dictionary
at the beginning of the program. Grab the dictionary from below, and put into your code after all the necessarity imports.
box = {
    "x": 200,
    "y": 200,
    "w": 40,
    "h": 40
}

1st Function Specification: handle_drag
  • Docstring
    :
"""
This function is called when the mouse is moved while one of its buttons is
pressed down. Moves a box on the screen the same amount as the cursor moved.
"""
  • Parameters
    :
    • mouse x coordinate (integer)
    • mouse y coordinate (integer)
    • x coordinate change (integer)
    • y coordinate change (integer)
    • mouse button (integer)
    • pressed modifier keys (integer - not relevant, but needs to be defined)
The function must move the box by changing its x and y coordinates by an amount equal to the cursor's movement along each axis. The library calls this function repeatedly while the cursor is moving, and the change of coordinates is given as difference from the cursor's position at the time of the previous call. Using this change information, the box can be made to move based on the cursor's movement (regardless of cursor's actual position).
You know your function works correctly if the box moves without any jumps when the cursor is moved while a button is held down.

2nd Function Specification: draw_box
  • Docstring:
"""
Draws a box into the application window.
"""
Open sweeperlib.py and read the instructions from the set_draw_handler function's docstring. You can also look at the example at the beginning of his exercise page. The box's position needs to be read from the box dictionary. Use the space character " " as the box's sprite key.

3rd Function Specification: main
  • Docstring:
"""
Creates an application window and sets handler functions for dragging and
drawing. Starts the application.
"""
The main function needs to create the application window using the create_window function from the library, and set handler functions for events with set_drag_handler and set_draw_handler functions. Check the documentation to see how these work. You can choose the window's size and background color freely. At the very end, this function has to start the application using the start function.

Testing:
if __name__ == "__main__":
    main()
Warning: You have not logged in. You cannot answer.

Course Project Exercises 2

Choose on of these. These tasks are not required for minimal course completion.

Mine Assignment: Mine Time

Randomness is a rather important aspect in games, and in general important enough to have its own programming tools. This exercise will help you when it's time to generate a mind field in the Minestomper course project. You'll also learn about drawing graphics with game libraries.
Learning goals: Getting familiar with the random module and implementing a suitable randomization for mine placement. The basics of drawing game graphics. Implementing a draw handler with the sweeperlib module.
Goal: A program that places a specified number of mines into random tiles in a field, and shows the result in a game window.

Introduction:
This exercise uses the same sweeperlib module as the previous one. In addition you will need the minestomper graphics package and unpack its contents into a folder of your choice.
Because the draw handler cannot have any parameters, it's not possible to hand the field to it as an argument. Therefore the field needs to be made available to all functions in the program through some other means. In this exercise we'll use a dictionary that holds the game state - this is the best way to do this with our current knowledge. Place the following snippet into your code immediately after imports:
state = {
    "field": []
}
Naturally the empty list will be replaced with a two-dimensional list that represents the field once the program is running. Note that the checker requires your program to have this dictionary.

1st Function Specification: place_mines
  • Docstring
    :
"""
Places N mines to a field in random tiles.
"""
  • Parameters
    :
    • field to mine (2-dimensional
      list
      )
    • list of available tiles (list of coordinate pair
      tuples
      )
    • number of mines to place (integer)
The function chooses N coordinate pairs from the list of available tiles and places a mine into each of the selected tiles in the field (mine is marked with "x"). This can be done in multiple ways - just make sure not to mine the same tile twice! Mined coordinate pairs should therefore be removed from the list of available tiles.

2nd Function Specification: draw_field
  • Docstring:
"""
A handler function that draws a field represented by a two-dimensional list
into a game window. This function is called whenever the game engine requests
a screen update.
"""
Open sweeperlib.py and read the docstring of set_draw_handler to learn how to implement a draw
handler
. The field must be retrieved from the state dictionary using the "field" key. When drawing tiles, you need to multiple their list indices by the size of the tile sprite (which you can see by looking at the tile image file properties). The part where you iterate through the field will be very similar to a previous exercise.

3rd Function Specification: main
def main():
    """
    Loads the game graphics, creates a game window and sets a draw handler for it.
    """
    
    sweeperlib.load_sprites(#you need the path to the sprites folder here)
    sweeperlib.create_window(600, 400)
    sweeperlib.set_draw_handler(draw_field)
    sweeperlib.start()

Function Testing:'
The main program must be placed inside the if __name__ == "__main__":
conditional statement
. The main program's purpose is to test your functions. This is done by creating a 15x10 field where we place 35 mines. The mines are placed by
calling
the place_mines function once. The field can be created with this snippet:
field = []
for row in range(10):
    field.append([])
    for col in range(15):
        field[-1].append(" ")

state["field"] = field
In addition you need the aforementioned list of available coordinates. This can be created with the following snippet. Pay attention to the connection between dimensions, rows, columns, and coordinates.
available = []
for x in range(15):
    for y in range(10):
        available.append((x, y))
After this you should first call your place_mines function, followed by the main function.

Use Examples:
The result should look like this.
Warning: You have not logged in. You cannot answer.

Spectral Assignment: Pointing is Rude...

...but oh so practical - at least when it comes to pointing things on the screen with a mouse. This exercise teaches you a couple of skills that will be important in Spectral Matters: displaying a figure inside an application window, and reading mouse clicks from it.
Learning goals: Drawing a figure using matplotlib and guilib together. Implementing a mouse handler for the figure. Storing event information to program memory.
Goal: A program that draws a figure, and reports the x and y data values of the clicked point.

Introduction:
A figure embedded into an application window consists of three parts: the canvas, the figure, and a subplot. Our guilib's create_figure returns all of these - your task is to draw using them. The former is a matplotlib Figure object - it's documentation is here. Note that the figure itself cannot be drawn to - you need to use the subplot instead. The subplot is a matplotlib Axes object - documenation here here In some cases the figure is not displayed until the canvas object's draw method is called - you need to do this in your code even if you can see the figure without it.
The mouse
handler
follows the same principles as the button handler from the last exercise but it does have one parameter: a mouse event (documentation). This event is an
object
with a few important
attributes
. The key ones are:
  • x and y which are the screen coordinates that were clicked
  • button, the button that was clicked (1 = left, 2 = middle, 3 = right)
  • xdata and ydata that are the axis values in the clicked point
The exercise also needs a similar
dictionary
as the last one but due to its broader nature, we'll name it state
because it contains general information about the program's state. A new key-value pair is added to the dictionary. You should save all clicked data values to this value as
tuples
.
state = {
    "textbox": None,
    "points": []
}

1st function specification: choose_point
  • Docstring
    :
"""
Receives a mouse event from a mouse click and reads the x and y data 
values from it. The values are printed into a textbox, and saved to a list
in the program's state dictionary.
"""
  • Parameters
    :
    • mouse event (matplotlib MouseEvent object)
The function needs to read the axis values from the mouse event it receives. These values are in the xdata and ydata attributes. The values are written into the textbox with two decimal precision - see the message format from the examples. This point should also be appended to the points list inside the state dictionary. This is important because in the course project you need to access previously selected points. When points are saved into the state dictionary like this, they are conveniently available.

2nd function specification: main
  • Docstring:
"""
Creates a user interface that contains an interactive figure and a textbox.
A plot based on data received as parameters is drawn into the figure.
"""
  • Parameters:
    • x axis data (list of floats)
    • y axis data (list of floats)
This function has the same purpose as the one in the previous exercise. This time the the interface is split vertically. The upper frame contains the figure. You can check the create_figure docstring for information on how to add one. The handler should be the choose_point function we just implemented. The bottom frame contains the familiar textbox. In addition the function should plot the data it receives.
An example of the result can be found at the end.

Function Testing:
if __name__ == "__main__":
    datax = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0]
    datay = [0.0, 0.19, 0.36, 0.51, 0.64, 0.75, 0.84, 0.91, 0.96, 0.99, 1.0, 0.99, 0.96, 0.91, 0.84, 0.75, 0.64, 0.51, 0.36, 0.19, 0.0]
    main(datax, datay)

Use Examples:
The interface should look like this. Exact measurements can differ.
Warning: You have not logged in. You cannot answer.

Cutting Assignment: No Holds Barred

Most libraries tend to have two ways for handling keyboard: reacting to changes in key states; or reading the state of the keyboard continuously. The former is ideal for programs where it's only relevant to handle individual key presses so that a function can be attached to either positive or negative edge of the key press, i.e. either to when the key is pressed down or when it is released. This approach is usually simpler to implement but its critical limitation is that it cannot handle situations where holding a key down is supposed to do something. In this case the only option is implement a logic that follows the state of the keyboard constantly.
Learning Goals: Learn how to handle key presses and holds using the sweeperlib so that both can be handled separately. Implementing a threshold value for holds.
Goal: A program where the user can adjust the number of counter using the keyboard.

Introduction:
Since
handler functions
have their arguments dictated by the library, they cannot pass information to each other via conventional means. Instead, the program can have a main program level
dictionary
that can be accessed and modified by all functions. For purposes of checking this task, it is required to have a specific key in the dictionary that maintains the value of the counter. You also need to maintain how long each key has been held down in this dictionary in order to implement the update logic. Besides the dictionary, you also need to define the threshold value for holds as a constant. Do not change the value of this constant!
THRESHOLD = 10
state = {
    "counter" 0,
    "holds": {}
}

1st Function Specification: draw
  • Docstring
    :
"""
Updates the counter value on screen by drawing the background, and then the counter's value.
The value of the counter is obtained from the "counter" key in the state dictionary, and it
is expected to be an integer.
"""
This function doesn't have parameters or return values. Open sweeperlib.py and read the docstring of set_draw_handler to learn how to implement a draw
handler
. This function should get the value of "counter" key from the state dicionary, and display its value as text on the screen. That is all.

2nd Function Specification: update
  • Docstring:
"""
Updates the value of a counter based on the state of up and down arrow keys, and shift keys.
The up arrow increases the value of the counter once when it is pressed down, and continuously
if held down longer than the threshold value. The down arrow decrements the counter similarly. 
If either shift key is held down, the change of the counter is tenfold. 
"""
  • Parameters
    :
    • elapsed time since the function was last called (not used in this task)
This function updates the value of the "counter" key in the state dictionary using the following logic:
  • if either up or down arrow was just pressed down, the counter is modified by one unit;
  • if an arrow key has been held down longer than the threshold value, the counter is modified by unit;
  • if either shift key is held down at the same time, the counter modification is ten units instead;
  • if an arrow key is not held down, its hold counter is reset to 0
Both arrow keys need to have their own hold counter in the state dictionary that tracks how many update calls its been held down for. The purpose of the threshold value is to enable adjusting the value accurately with single presses, and fast with holds. The update function is called 60 times per second by default, and it's basically impossible for most humans to hold a key down for 1/60th of a second. The threshold value is introduced to give some leeway for situations where precise adjustment is needed.
Note that the arrows are considered of equal priority. If both of them are considered active at the same time, the counter should not change.

3rd Function Specification: main
def main():
    sweeperlib.create_window(800, 600)
    sweeperlib.set_draw_handler(draw)
    sweeperlib.set_interval_handler(update)
    sweeperlib.start()

Allowed filenames: *.py

Warning: You have not logged in. You cannot answer.

Duck Assignment: Flight path

In this assignment we are launching a box into air and drawing its flight path using sweeperlib library. Box is drawn in real-time as its coordinates are being updated.
Learning Goals: Calculating velocity vectors from polar coordinates, updating coordinates in real-time by object's velocity. Implementing simple gravity.
Goal: A program that shows a duck's flight path after a launch.

Introduction:
This task uses the same library module as the previous one. You'll also need the duck game graphics package, which you can extract into the same folder with your code. You'll find these in the resources section of this assignment. YOu'll also find a template where you should place the functions implemented in this exercise. The template comes with a keyboard interface for launching the duck, and a draw handler for drawing the interface.

1st Function Specification: initial_state
  • Docstring
    :
"""
Puts the game back into its initial state: the duck is put back into the
launch position, its speed to zero, and its flight state to False.
"""
The function updates initial values into the game dictionary. The initial value for both coordinates is 40, the speeds are set to 0, and the "flight" key's value is set to False.

2nd Function Specification: launch
  • Docstring
    :
"""
Launches a duck and calculates its starting velocity. Stores x and y velocity
components to the game dictionary.
"""
The function uses angle and force to calculate velocities along each axis. This calculation has been touched on previously in a certain early assignment. The function also sets "flight" to indicate that a launch has happened, allowing flight function to begin updating duck's values.
This function does not have return values or parameters. Instead it makes changes directly to the values of a global dictionary game.

3rd Function Specification: flight
  • Docstring:
"""
Updates duck's x and y coordinates based on corresponding velocity vectors.
"""
  • Parameters:
    • elapsed (
      float
      )
Interval function is called approximately every 1/60 second (slight inaccuracy is to be expected). The elapsed parameter holds the actual elapsed time since the function was last called. This parameter can be ignored during this exercise but the library's function call uses it.
After a launch the function updates new coordinates based on velocity. Due to the duck's superior aerodynamic properties, air friction can be completely ignored. Therefore the only external force affecting the duck's velocity is gravity, and it only affects the y component of velocity. Use 1.5 as the value for gravitational acceleration. This value is subtracted from the y velocity every time the function is called.
When the duck's y coordinate drops to zero or below, the flight has ended. The initial_state function should be called to communicate this change to the game logic. Note that this function should not do anything if the duck hasn't been launched. The "flight" key indicates this state.

Use Examples:
Assignment is slightly unusual since we cannot simply compare input values to expected outputs. Therefore we have also included a few numbers on the background of the UI. Box should pass through these numbers when using according angle and force values. Use these numbers for testing your program.
Number Angle Force
1 40 30
2 40 40
3 80 35
4 90 35
5 50 45

Resources:
sweeperlib.py
sprites.zip
flight_template.py
import math
import sweeperlib


WIN_WIDTH = 1200
WIN_HEIGHT = 600
GRAVITATIONAL_ACCEL = 1.5

game = {
    "x": 40,
    "y": 40,
    "angle": 0,
    "force": 0,
    "x_velocity": 0,
    "y_velocity": 0,
    "flight": False
}

def initial_state():

    *** Write your box initialization function here. ***

def launch():

    *** Write your box launching function here. ***


def flight(elapsed):

    *** Write your flight path updating function here. ***


def draw():
    """
    This function handles interface's and objects drawing.
    You do NOT need to modify this.
    """
    sweeperlib.clear_window()
    sweeperlib.draw_background()
    sweeperlib.begin_sprite_draw()
    sweeperlib.prepare_sprite("x", game["x"], game["y"])
    sweeperlib.draw_sprites()
    sweeperlib.draw_text("{}°\tforce: {}".format(game["angle"], game["force"]), 10, 505)
    sweeperlib.draw_text(
        "Q: Quit  | "
        "R: Reset |  "
        "←/→: Set angle |  "
        "↑/↓: Set Force  |  "
        "Space: Launch",
        10, 560,
        size=20
    )
    sweeperlib.draw_text("1", 380, 175, size=22)
    sweeperlib.draw_text("2", 830, 225, size=22)
    sweeperlib.draw_text("3", 170, 455, size=22)
    sweeperlib.draw_text("4", 50, 455, size=22)
    sweeperlib.draw_text("5", 700, 455, size=22)


def keypress(sym, mods):
    """
    This function handles keyboard input.
    You do NOT need to modify this.
    """
    key = sweeperlib.pyglet.window.key

    if sym == key.Q:
        sweeperlib.close()

    if sym == key.R:
        initial_state()

    if sym == key.RIGHT:
        game["angle"] -= 10
        if game["angle"] < 0:
            game["angle"] = 350
    elif sym == key.LEFT:
        game["angle"] += 10
        if game["angle"] > 350:
            game["angle"] = 0

    if sym == key.UP:
        if game["force"] < 50:
            game["force"] += 5
    elif sym == key.DOWN:
        if game["force"] >= 5:
            game["force"] -= 5
        else:
            game["force"] = 0

    if sym == key.SPACE:
        launch()


if __name__ == "__main__":

    sweeperlib.load_sprites("sprites")
    sweeperlib.create_window(width=WIN_WIDTH, height=WIN_HEIGHT)
    sweeperlib.set_draw_handler(draw)
    sweeperlib.set_keyboard_handler(keypress)
    sweeperlib.set_interval_handler(flight)
    sweeperlib.start()

Warning: You have not logged in. You cannot answer.

Course Project Exercises 3

And finally choose on of these. These tasks are not required for minimal course completion.

Mine Assignment: Flood Survey

Floodfill is a basic algorithm that has all kinds of uses in programming. For instance it can be used to determine the size of any limited area with arbitrary shape. The fill tool of drawing programs is also based on it. Floodfill can also be used to navigate labyrinths or calculate how far a game character can move in varied terrain. Coincidentally it also plays a critical role in Minestomping where there's a need to open empty tiles in a way that expands to every direction without revealing the mines. It's not the easiest algorithm to figure out without any programming experience so we've included a step-by-step guide into this assignment.
In this exercise a probe droid is exploring the surface of a planet ja marking unknown territory as safe while avoiding areas that were previously marked as dangerous.
Learning goals: Understand how the floodfill algorithm works and learn about implementing somewhat complex algorithms in Python. Removing items from lists without turning the program into a slog.
Goal: A program that explores connected unknown tiles on a map.

Introduction:
You can draw the field similarly as in the last exercise. Grab the draw_field function from there. The main function is also mostly the same (see below).

1st function specification: floodfill
  • Docstring
    :
"""
Marks previously unknown connected areas as safe, starting from the given
x, y coordinates.
"""
  • Parameters
    :
    • the planet to explore (2-dimesional
      list
      )
    • starting point x coordinate (integer)
    • starting point y coordinate (integer)
The map of the planet contains two kinds of characters: unknown " " and dangerous "x". A safe tile is marked with "0". Your task is to start from the initial point and proceed to mark all connected tiles as safe. If the initial point is dangerous, nothing is done. You need to follow the provided step-by-step instructions for the algorithm quite accurately. In particular you need to avoid using
recursion
(you know you're using it if your floodfill function calls itself at any point)
.
The floodfill is started by creating a list with one item: a tuple that contains the starting point's coordinates. After initializing the list, the program moves on to a
loop
that runs until the entire connected area is filled. Each
iteration
of the loop proceeds as follows:
  1. a new item is taken for processing from the aforementioned list (note: it has to be removed) - there's a method for this
  2. it is marked as safe by replacing the character in those coordinates of the planet list with "0"
  3. iterate through all surrounding coordinates (8 total, but be mindful of borders!) (see the ninja exercise for how to do this)
  4. each tile that is unknown is added to the aforementioned list
This way the list that contains coordinate pairs keeps growing at the same time as it is consume, and only becomes entirely empty once all connected unknown tiles have been explored. Marking a tile as safe is done at the beginning of each iteration. We know the tile is safe because it was added to the list on a previous iteration, and the algorithm only adds unknown tiles to the list.
The function doesn't return anything.
Tip: In order to get an idea of what's going on inside your algorithm, place a print that prints out the contents of the flood list inside your loop. This allows you to see how the flood progresses from tile to tile. Just don't leave the print there when submitting your code for checking, printing tends to be very slow...

2nd function specification: main
  • Docstring:
"""
Loads the game graphics, creates a game window, and sets a draw handler
"""
  • Parameters:
    • planet (a list that represents the planet, see below)
This function is based on the previous main function. We do note however that the planet shown below does not fit nicely into a 600x400 window. Change the window size accordingly - the best way to do this is to use the len function to get the field's dimensions and multiply them with the sprite dimensions.

Function Testing:
You need a main program that calls your functions for testing. You can use the following planet in your main program:
planet = [
    [" ", " ", " ", "x", " ", " ", " ", " ", " ", " ", " ", "x", " "], 
    [" ", " ", "x", "x", " ", " ", " ", "x", " ", " ", " ", "x", " "], 
    [" ", "x", "x", " ", " ", " ", " ", "x", " ", " ", "x", "x", " "], 
    ["x", "x", "x", "x", "x", " ", " ", "x", " ", "x", " ", " ", " "], 
    ["x", "x", "x", "x", " ", " ", " ", " ", "x", " ", "x", " ", " "], 
    [" ", " ", "x", " ", " ", " ", " ", " ", " ", "x", " ", " ", " "]
]
Call the floodfill function with a suitable starting point. Finally call the main function so you can see what the floodfill did.

Speed Requirements:
Unlike every exercise in this course, this one will check how fast your code executes. Slow execution will lead to lower points or completely failing. The primary cause for slowness is bad removal of items from the list. If items are removed from the beginning or middle of the list, a chain reaction is caused where all the remaining list indices must be updated (imagine the items being placed one slot closer to the beginning, one at a time). You won't notice the difference with a small field, but will notice with the 100x100 field included in the tests. Removals must be done from the end of the list.
Furthermore, remove is not a good method in this task beause it removes the first matching item from the list. This becomes a problem because the algorithm can place the same coordinate pair multiple times into the list. So even if you try to remove the last item, it is likely that one of its copies earlier in the list gets removed instead. Investigate list methods and find a more suitable method for this task.
Another way to make the checking time out is to make an
infinite loop
. For instance if your algorithm doesn't make sure it doesn't enter tiles it has already visited, it will end up visiting the same tiles over and over infinitely.
Executing the tests under 10 seconds is a requirement for full points. Furthermore, if the execution goes longer than 20 seconds, the checking will be interrupted, and you will get no other feedback except a notification that it took too long. This is to prevent the checking backend from getting blocked by too many slow processes running.
Remember to remove all prints from your flood algorithm!
Warning: You have not logged in. You cannot answer.

Spectral Assignment: Dataminer in the Junkyard

This exercise teaches you a basic skill that is required for all kinds of data processing: reading data files. You've received a request from a researcher who konws nothing about programming. In addition they are very, very messy with their files - the data folders can include all kinds of trash like vintage meme pictures. Some data files are broken too. In general it's preferable for data readers to be able to find the real data from somewhat less organized folders. Program requirements are hard to keep in mind when saving things to the hard drive without much thought.
Learning goals: Reading data from multiple
files
to
data structures
in a program. Figuring out broken files and the correct way to handle them. Reading data rows.
Goal: A program that reads data from multiple files to program memory.

Introduction:
To make this task seem a bit more relevant we've given you a script that creates a bunch of random data files (check "resources"). All files generated by the script are intact, so you have to break some of them manually. While you're at it, copy your holiday pictures into the same folder to confuse your program a bit more. Run the script in the terminal with a
command line argument
that indicates which folder you want the data to go to.
You can also copy the main function from the Just an Ordinary Window exercise.

1st function specification: read_data
  • Docstring
    :
"""
Reads all data files from the given folder. Skips files that don't have the
.mydat extension and files that have errors in them. The names of faulty .mydat
files are reported to the user.
"""
  • Parameters
    :
    • target folder's path (
      string
      )
  • Returns
    :
    • contents of the data files as a
      data structure
      (list of 3 item tuples)
    • names of faulty .mydat files (list of strings)
The function has to go through the contents of the folder and find all all .mydat files, and read their contents (other files are skipped silently). Data is appended to the program's data structure only when the end of each file is reached. If an error is encountered while reading a file, all data from that file is discarded, and the file's name is added to the list of faulty files. Correct data rows will look like:
Tomomi, 154.3578,12.9402
In other words each data row has three comma-separated values. The first one is always string. Each data row is parsed into a
tuple
that contains a string, and two
floats
, e.g.:
("Tomomi", 154.3578,12.9402)
These tuples should be appended to a temporary list first, and only added to the actual data list when the entire file has been read. This data list is returned when all files have been processed. You should also keep in mind that files may or may not have an empty line at the end. Depending on your implementation this can require additional processing.

2nd function specification: open_folder
  • Docstring:
"""
A button handler that opens a dialog the user can use to choose a data folder.
Loads data from the selected folder and reports the number of rows read and the
names of any faulty files into a textbox.
"""
This function should open a folder dialog (with a guilib function), and use its return value to call the read_data function. When the data has been read, the names of all faulty files are written (e.g. as "Faulty file: x") to the textbox, and finally the number of data rows read.

Function modification: main
Change the test button's label to "load" or something else descriptive, and the handler to the open_folder functin.

Function Testing:
if __name__ == "__main__":
    main()

Use Examples:
Example picture

Resources:
generate_data.py
import os
import sys
import random

NAMES = ["Squall", "Cloud", "Celes", "Yuna", "Pikachu", "Bulbasaur", "Winnie the Pooh", "Eeyore", "Eunji", "Tomomi", "Haruna", "Seungyeon", "Ihsahn", "Abbath", "Fenriz"]

CHARS = "abcdefghjiklmnopqrstuvwxyz"

def gen_data(folder):
    os.makedirs(folder, exist_ok=True)
    for i in range(10):
        with open(os.path.join(folder, "".join([random.choice(CHARS) for x in range(random.randint(4, 10))]) + ".mydat"), "w") as target:
            for i in range(random.randint(4, 20)):
                target.write("{},{:.4f},{:.4f}\n".format(
                    random.choice(NAMES),
                    random.random() * 1000,
                    random.random() * 100
                ))                
    
if __name__ == "__main__":
    try:
        gen_data(sys.argv[1])
    except IndexError:
        print("Usage:")
        print("python generate_data.py folder")    

Warning: You have not logged in. You cannot answer.

Cutting Assignment: Image cutting essentials

The final goal of the image cutter project is to save regions from an image as new images. In order to achieve this goal relatively effortlessly it's best to borrow some wisdom from the great ancient ones. Some basic disk content manipulation is also needed. This task will gives you the essential tools for saving images.
Learning Goals: Basic of using Pillow. Handling of file system paths, checking them, and creating them.
Goal: A prgoram that prompts for edge coordinates for a cut, and then takes the cut from the chosen image.

Introduction:
In order to process images on this level, you're going to need the Pillow library. It's not built into Python, and needs to be installed:
pip install Pillow
Not that for historical reasons the module name used in code for the library is PIL rather than Pillow. This just to clear any ambiguity when looking at import statements in examples of the documentation. The link leads directly to the only page from Pillow's documentation that is needed for the simple processing in this task. Reading the docs and figuring out how to use Pillow is considered part of the task.
The workhorse of the previous exercise, prompt_input, is once again needed here as well. So grab its source code into your new code file before starting.

Function Modification: prompt_input
  • Docstring
    :
"""
Prompts an integer from the user using the given prompt string. The integer
is checked against a minimum value that is taken from an optional argument, and
defaults to 0. If the user gives an invalid input, the provided error message
is printed.
"""
  • Parameters
    :
    • prompt string
    • error message (string)
    • minimum value (integer) -
      default value
      0
  • Returns
    :
    • given integer that is larger than the minimum
This function is modified so that it can be called with an
optional argument
which defaults to 0 if not provided. Use this new parameter to replace the previously used zero as the minimum value that the input is checked against.

1st Function Specification: prompt_path
  • Docstring:
"""
Prompts the user to provide a path using the given prompt string. This 
function checks whether the path matches an existing file, unless the last
optional parameter has a value of True. If checked, and the file does not exist
the user is given the error message frm the second parameter and prompted 
again.
"""
  • Parameters:
    • prompt string
    • error message (string) - default value ""
    • flag to indicate whether the prompt is for a new file - default value False
  • Returns:
    • provided path (string)
This function has two modes. In its default mode it prompts for a path that is expected to lead to an existing file. In this mode a path is prompted until the user provides a valid path. However, if the last parameter's value is True, the function operates with the assumption that the path is for a new file, and no checking is done. You can find a tool for checking paths in the os.path module.

2nd Function Specification: prompt_values
  • Docstring:
"""
Prompts the user for edge coordinates of a rectangle and returns them as a 
dictionary. Only positive integers are accepted. In addition, the right edge
of the rectangle must be larger than the left, and similarly the bottom edge
must be larger than the top edge. The returned dictionary contains these edges
in the keys "left", "right", "top", "bottom".
"""
  • Returns:
    • dictionary that has the provided values in its four keys
Here we want a function that asks the user to provide edge coordinates for a rectangle to be used in the cut. This function should use the recently modified prompt_input function. The left edge should act as the minimum value for the right edge, and top edge for the bottom edge. The function should put the values into
a dictionary using the keys given in the docstring, and return it.

3rd Function Specification: perform_cut
  • Docstring:
"""
Cuts a region from the provided image and saves it as a new image in the 
requested location. The region's dimensions are taken from the provided 
dictionary from the keys "left", "right", "top", "bottom". As the origin for 
the image is at the top left corner, the bottom coordinate should be larger
than the top coordinate. If the region goes outside the source image, the cut
is not performed.
"""
  • Parameters:
    • source image path (string)
    • cut parameters (dictionary)
    • result image path (string)
At this point it's good to look into how Pillow processes images. Your task is to write a function that opens the source image, checks its dimensions against the cut parameters, and then finally performs the cut if the region fits entirely inside the image. Before saving the cut as a new image, the function has to make sure the target folder exists. In order to do this you should look into the os module to find tools for creating folders if needed.

Function Testing:
You can test your program as a whole by making a main program that prompts the user for paths for the source image and the result image using the prompt_path function, as well as the cut parameters with the prompt_values function. You can use the image below for testing.
You should get the top right square from the image using edges 52, 2, 94, 44.

Allowed filenames: *.py

Warning: You have not logged in. You cannot answer.

Duck Assignment: Boxfall

In this assignment it's raining boxes. When dropping boxes, it's important to make sure they don't end up inside one another. In our duck plans this mechanism is needed when a target gets blown out from underneath a box, and the box needs to fall accordingly.
Learning goals: Applying gravity to boxes. Collision detection among a group of objects.
Goal:' A program that drops a bunch of randomly placed boxes down from the sky so that they pile up on top of each other.

Introduction:
Just like in the previous assignments, once again all data should be placed inside a
dictionary
. Use the dictionary shown below. You should also pick up the habit of defining important costants like window size with, well,
constants
.
WINDOW_WIDTH = 1200
WINDOW_HEIGHT = 600
GRAVITY = 1.5

game = {
    "boxes": []
}

1st Function Specification: create_boxes
  • Docstring
    :
"""
Creates a speficied number of boxes with random positions inside the specified
area. Boxes are represented as dictionaries with the following keys:
x: x coordinate of the bottom left corner
y: y coordinate of the bottom left corner
w: box width
h: box height
vy: falling velocity of the box
"""
  • Parameters:
    :
    • number of boxes (integer)
    • minimum height for placement (integer)
  • Returns
    :
    • a list that contains box dictionaries
The function randomizes a set of boxes. The boxes are square (i.e. width == height). Boxes must be placed inside the window, and above the desired minimum height. The boxes are allowed to overlap (the dropping algorithm takes care of this problem). The falling velocity of each box is set to 0. Both dimensions are set to 40. The boxes are placed inside a list that is returned.

2nd Function Specification: drop
  • Docstring:
"""
Drops rectangular objects that are given as a list. Each object is to be
defined as a dictionary with x and y coordinates, width, height, and falling
velocity. Drops boxes for one time unit.
"""
  • Parameters:
    • List of dictionaries, each representing a rectangle
The function goes through all boxes in the list and figures out whether each of them should fall or stay in place. In order to do this, boxes must be iterated through in ascending order of height (measured from the top of the box). Boxes that are lower will be dropped first. A box stays still if its bottom touches the ground (y <= 0) or the top of another box. In both cases the box's y coordinate is set to the level where it has stopped (i.e. zero, or top of the box below it).
Example boxes. Red boxes are falling. Iteration order is shown with numbers. Box 8 is falling because box 7 below it is dropped first.
A box that is falling has its falling velocity incremented by the gravital acceleration value, and then its y coordinate adjusted by the falling velocity. The boxes will fall at increasing velocity. Because of this it is also possible that a box will fall so fast that it passes through another box without ever touching it - this needs to be prevented in the implementation.
Note! Although the program itself only deals with 40x40 boxes, the function code itself is to be written in a way that it works for any rectangles of any size. Your code needs to read each box's width and height from the dictionary representation. The checker will also test the function with boxes of varying sizes.
Hint: When comparing boxes to other boxes, it is best to proceed downward from the current box. I.e. if we are currently on box 5 in the above picture, the comparisons would be made against boxes 4, 3, 2, and 1.

3rd Function Specification: draw
  • Docstring:
"""
Draws all boxes into the window.
"""
The draw handler needs to be implemented similarly to the previous ones. However, since there are multiple boxes now, a loop is needed for iterating through all of them. Make sure to call prepare_sprite once for each box. Like previously, use " " as the sprite key.

Testing:
You can use the main function from the previous assignment as the basis for testing. You just need to replace the draw handler with the one you just made, and the update handler with this one:
def update(elapsed_time):
    drop(game["boxes"])
After a while all boxes should have settled down in a way that they no longer overlap each other, and are "safely" standing on something. If you want to see what happens to the boxes, you can slow down the falling by setting the update handler's interval higher with its optional argument. This can be useful in finding bugs.
Warning: You have not logged in. You cannot answer.
?
  1. Description
  2. Examples
Absolute path is an operating system term that refers to the full "address" of a file or folder. Absolute path is written starting from the disk root. When absolute path is used, the current directory does not matter. Absolute paths are usually avoided in code - especially in applications that are meant to be shared. Another user is very unlikely to have the exact same folder structure as the application's developer. In particular if an absolute path refers to the user's home folder, it is very likely not going to be the same for another user.
Ajonaikaisesta (engl. run time) puhuttaessa määreenä on se aikaväli, kun ohjelma on käynnissä. Esimerkiksi Pythonissa virheet (syntaksivirheitä lukuun ottamatta) tarkastetaan ajonaikaisesti. Ohjelma saattaa siis olla käynnissä ja toimia tiettyyn pisteeseen saakka, kunnes törmätään käsittelemättömään poikkeukseen – ajonaikaiseen virheeseen (engl. run time error).
  1. Description
  2. Esimerkit
Alustamisella (engl. initialize) tarkoitetaan yleisesti jonkin arvon asettamista muuttujalle muuttujan luonnin yhteydessä. Pythonissa ei ole mahdollista luoda muuttujaa, jolla ei ole myös jotain arvoa. Niinpä tyypillisesti käytetäänkin sanamuotoa ”muuttuja alustetaan arvolla x”, millä tarkoitetaan sitä, että muuttuja, joka luodaan, saa luomisen yhteydessä (eikä vasta joskus myöhemmin) arvon x.
  1. Description
  2. Esimerkit
Argumentti (engl. argument) on funktiokutsussa käytettävä arvo, joka välitetään kutsuttavalle funktiolle. Funktiokutsun alkaessa argumentit sijoitetaan parametreiksi kutsuttuihin muuttujiin, joiden kautta arvoihin pääsee funktion sisällä käsiksi.
Arvo (engl. value) on konkreettista, tietokoneen muistissa sijaitsevaa tietoa, jota käytetään ohjelman suorituksen aikana. Arvoilla on tyyppi ja sisältö; esimerkiksi numero 5 on tyypiltään kokonaisluku, jonka sisältö on 5. Useimmiten arvot liitetään muuttujiin, mutta myös operaatioiden ja funktiokutsujen paluuarvot sekä koodissa sellaisenaan esiintyvät arvot ovat arvoja. Käytännössä siis kaikkea konkreettista mitä ohjelma käsittelee voidaan kutsua arvoiksi.
Assignment is related to variables and values. A typical figure of speech is "assigning to a variable" which means giving a certain value to a variable (e.g. x = 5). More specifically, in Python, assignment to a variable means creating a connection between the name and value of the variable - the variable is a way to find the value.
Similar expressions that can be used to mean the same thing are: "saving to a variable", "storing to a variable", "referring to a variable", "stuffing a value into a variable"... etc.
Assignment operator i.e. the = character is used for variable assignment. When using the operator, the target variable must always be on the left side and the value (or statement that produces the value) on the right side.
Attribute is a value that belong to an object, sometimes also called property. It's a name that belongs to the object's internal namespace and it can be accessed through the object: timestamp.tm_hour would read the hours from a timestamp.
  1. Description
  2. Kurssin avainsanat
Avainsanat (engl. keyword) ovat ohjelmointikielessä kielen käyttöön varattuja sanoja, joilla on erityinen merkitys. Hyvät tekstieditorit tyypillisesti merkitsevät avainsanat muista nimistä eroavalla tavalla (esimerkiksi lihavoinnilla tai tietyllä värillä). Avainsanat ovat yleensä suojattuja, eli samannimisiä muuttujia ei voi luoda. Yleisiä avainsanoja Pythonissa ovat esimerkiksi funktioihin liittyvät def ja return. Avainsanat ovat siis osa ohjelmointikielen kielioppia.
Boolean is the most simple data type in programming languages because it has only two values: true (True in Python) and false (False in Python). Things like comparison operators return booleans, and they are often used in conditional statements and while loops. In Python all values are equivalent to one of the boolean values. Generally all so called empty values (0, "", None etc.) are equal to False while the rest are equal to True.
  1. Description
  2. Extra info
Boolean operator refers to Boolean algebra which deals in values of truthfulness. These operations include and, not, and or - all familiar from conditional statements. Out of these and is True if and only if both operands are True; or is True if at least one operand is True; and not is True is its sole operand is False.
Branch is an execution path in the program that is mutually exclusive with other branches in the same control structure. For example in a conditional structure each if, elif and else define their own branches and only of them is executed.
Bug is an error in the program's source code. As the result of a bug the program either doesn't start at all, crashes during execution, doesn't work correctly in some situations, or can even cause severe security issues. Careful programming and testing - including rare edge cases - reduces the probability of bugs. Tracking down the part of code that causes a bug and fixing it is called debugging.
Buitin functions are function that are included in the Python core. They can always be used without importing any modules or libraries.
Callback is a common mechanism, especially in modern programming, where another part of the program - often made by someone else - is given a function it is to call during its execution. If a normal function call is like a phone call, a callback is a like a call request. If a part of the program uses a callback, it usually described what kind of a function it accepts - especially what parameters the function can/must have and what kind of a value it should return.
Where UNIX-based systems produce \n characters (newline) to indicate line breaks, Windows uses \r\n where the r is a carriage return character. It's a remnant from mechanical typewriters, and indicates the procedure of physically moving the typewriter head to the beginning of the line. In general this is just something that's good to know - Python treats both line breaks quite nicely.
Code block or block is a term used for liens of codes that belong to the same context. A block is formed of lines that have the same indentation level (although a block can also contain other blocks). Typical blocks are the executable parts of conditional structures i.e. the indented code lines that follow a condition. A block ends when a line with less indentation than ones belonging to the block is encountered.
Code file is a text file that contains executable code. A Python code file can be ran from the terminal by typing python code.py where code.py is the file's name. When you run a code file the return values of individual lines are not shown unless they have been specfically rpinted.
  1. Description
  2. Material example
  3. Basic use
Command line argument or parameter is a name used for additional information that is passed to a terminal program when it's started. Command line arguments are typically separated by spaces. E.g. in python code.py, code.py is actually a command line argument. Command line arguments can be accessed in Python from the sys module's argv variable.
Comparison operators are used for comparing values to one another. They are familiar from mathematics and can be used to compare size. Comparison operators return a boolean value, True or False, depending on the result of the comparison. Comparison operators are: <, <=, >, >=, == and !=
Comparison values are used e.g. in sorting lists. A comparison value is a value derived from a list item that is used instead of the item itself in sorting. For instance, if a list contains lists, a comparison value can be an item taken from a certain index of each inner list. It can also be a more complex derivative such as the sum of items or their mean value.
  1. Description
  2. Examples
Condition is used in this course to refer to the part of conditional statements and while loops that defines when the statement is true. Anything between the keyword that starts the stamement and the colon that ends it is basically its condition.
  1. Description
  2. Examples
Conditional statement is a line of code that defines a single condition, followed by an indented code block which defines what should be done if the condition is true. Conditional statements include if and elif statements, the latter of which cannot be present without the former. Conditional statements that are linked together form conditional structures. A conditional statement must always end with a colon and it must be followed with at least one indented code line.
  1. Description
  2. Examples
Conditional structure is a structure that consists of one or more conditional statements that branches program execution. Most of them have at least two branches: if and else. Between the two there can also be an indefinite number of branches under elif statements. It is also possible to have nothing but a single if statement in a structure. Each branch in a conditional structure has at least some code that defines what the program does in a situation falling under a condition.
As a whole a conditional structure is interpreted by checking the truthfulness of the first branch (if). If it evaluates to True, program execution continues to the code block inside the statement after which execution skips the rest of the structure. If it evaluates to False, other branches will be evaluated in sequence until one of them is True, or if none of them are, the else branch is executed.
  1. Description
  2. Examples
Constant is a named literal value. They are used especially when the same literal value is used repeatedly in a program. Named constants are also just in general more practical in code than seemingly arbitrary literal values because its meaning can be derived from its name. Likewise if the value needs to be changed it is much easier if you only need to change it in one place (where it's defined). Python doesn't actually have a way to define "real" constants - they are simply variables. The difference is implied by writing constant names in full upper case. E.g THE_ANSWER = 42.
Control structure is a common name for different programming structures that control the program flow in some way. Within this course this includes conditional structures, loops and exception handling.
Data (engl. data) on ohjelmoinnin asiayhteydessä mitä vaan tietoa, joka ei kuitenkaan yleisesti kata itse ohjelmakoodia. Yleensä datasta puhuttaessa tarkoitetaan yksittäisiä literaaliarvoja, muuttujien sisältämää tietoa tai jostain tietolähteestä (kuten tiedostosta tai verkko-osoitteesta) luettua tai sinne kirjoitettua tietoa. Nyrkkisääntönä voi kuitenkin pitää sitä, että koodi ja data ovat eri asioita, ja koodi käsittelee dataa. (Joissain yhteyksissä koodikin lasketaan dataksi, mutta näihin ei tällä kurssilla syvennytä.)
Data format is the "syntax" of a data file, and it defines how data has been saved to the file. Data format also defines what kind of data can be stored in the file. The basic idea of each data format is to enable the saving of data structures in a program in some format that also makes it possible to load them back in later. A data format can be based on some existing standard (e.g. JSON) but ultimately it's the programmer's responsibility to choose what data is relevant for the program and how to best represent it.
Data structure is a common name for collections that contain multiple values. The purpose of a data structure is to store data that consists of more than one value. There are various ways to make a data structure and each of them convenient means for adding, removing and modifying values. Data structures implement a way to bundle data together. Generally the difficult details involved have been hidden from the programmer.
Choosing data structures that serve the purposes of your program and are easy to handle in your code is essential. The most common structures in Python are list, tuple and dictionary. Another convenient structure is set which doesn't contain duplicate values. In addition to built-in structures, more can be found from the collections module.
On later courses you'll also become familiar with other important structures like trees and graphs.
Debugging is the process of hunting down and fixing programming errors i.e. bugs. There are many ways to track down bugs. One of the more common ones in Python is the error message it shows when a program crashes. Another common method to find errors is the use of debug prints. This means putting additional print function calls in the code temporarily to either see how far the code gets or what kinds of values variables have. Debugging is such an important part of programming that there are even specific debugging tools that have been developed. We don't use them on this course however.
Default value is a value that can be defined for a function parameter. It will be used for that parameter's value if its corresponding argument has not been given in a function call. E.g. in def prompt_length(question, maximum=10): function definition, the maximum parameter has been made optional by giving it the default value of 10.
  1. Description
  2. Definition
  3. Value lookup
  4. Modifying dictionaries
Dictionary is a data structure that assigns keys (usually strings) to its values. The advantage of using dictionaries is that descriptively named keys make code that handles the data structure much easier to read. Starting from Python 3.7 dictionary keys and values are guaranteed to be in the order they were added.
In Python docstring is a comment-like entity but it has a special meaning. A docstring is usually delimited with triple quotes (i.e. '''document''' or """document""". If a docstring is placed immediately below a function's def statement (indented!), it becomes the function's documentation that is shown with the help function. Likewise a docstring placed at the very beginning of a code file becomes the module's documentation. A good doctstring describes what a function does, and explains its parameters and return values.
Docstrings should not be used as comments! Outside of the aforementioned places, commenting should be done with actual comments (lines starting with #).
Epätosi (engl. false) on toinen kahdesta mahdollisesta totuusarvosta ja toisen, eli toden, vastakohta. Sitä voidaan pitää lopputuloksena loogisissa ja vertailuoperaatorioissa, jotka eivät pidä paikkansa. Esimerkiksi vertailuoperaatio 5 < 4 ei pidä paikkansa, joten kyseinen operaatio evaluoituu epätodeksi. Pythonissa epätotta merkitään avainsanalla False.
  1. Description
  2. Examples
Error message is the Python interpreter's way of informing about an exception in a program. The error message contains information about where in the program the exception happened, which line caused the exception, the exception's type (e.g. SyntaxError) and a short verbal description. Error messages are your best friends and reading them is a very integral programming skill. Don't be afraid of them, they are only there to help you find out what's wrong in the code!
Escape in programming terms means interpreting a character in an exceptional way. For instance "n" is just the letter n but "\n" is a newline character. In this example the backslash character \ causes the normal interpretation of the n character to be escaped and replaced by another interpretation. The backslash functions as an escape character. One typical use is including " in a string that's delimited with ": "donkey ear interval is 14\""
Evaluointi (engl. evaluation) tarkoittaa lausekkeen tai muuttujan arvon lopputuloksen määrittämistä. Suoritettaessa lauseet evaluoituvat joksikin tietyksi arvoksi.
Event is a programming cocept that is generally used in the context of interactive applications that run in real time. These applications usually have a main loop that monitors for events. Events include: user clicks with the mouse, user presses a key, a certain amount of time has passed etc. Handler functions can be attached to events, and they will be called whenever the event is detected. This makes programming of interactive programs much easier because there's no need to worry about how actions on the screen are detected when implementing the application itself.
  1. Description
  2. Examples
Exception is a scenario in programming where the program cannot proceed as instructed. Exceptions have a type (e.g. TypeError) that can be used in handling the exception within the program. Type can also be useful when trying to solve the issue if it is not intended. In most cases exceptions also come with a message that gives more details about what caused the issue. In Python exceptions are handled with try-except structures.
Exception is the base class of most common exceptions. We also call it the Pokémon exception because if you use it in a try-except structure it will catch all the exceptions. In most cases this is not a good thing. It makes interpreting problem situations more difficult for both the user, and you, the developer. The latter is due to the fact that it will also catch any mistakes you made in your code, and you won't get any useful information when the program isn't behaving correctly.
Execution or running means going through a program or code snippet so that the instructions written within are carried out by the computer. Python interpreter executes code one statement at a time. While this is ongoing the program is "running". Execution ends when there is no more code to run, there's an unrecoverable error or when the program ends itself.
File extension is the part of the file's name that is on the right side of the last period in the name. They are commonly used for indicating file types. Image files for instance often have .png or .jpg as their extension. Python code files usually have .py at the end (e.g. donkeyswings.py).
File handle is a special object that Python uses to refer to an opened file. Most important note is that the handle is not the same as the file's contents - the handle can be used to read the contents, or write to the file. A file handle is obtained with the open function with the file's location (path) and the opening as arguments. E.g. with open("donkey.txt", "r") as somefile: opens donkey.txt inside a with statement (where files usually should be opened), with somefile as the file handle.
Filename is the name of a file that consists of the file's actual name and a file extension. For instance, donkeyswings.py is a complete filename where the given name is donkeyswings and the extension is .py.
Inside code, filenames are always strings.
  1. Description
  2. Conversions
Floating point number or float is an approximation for decimal numbers used by computers. Computers can't handle real decimal numbers due to their architecture, and that leaves us with floats. Floats can occasionally cause rounding errors - something to keep in mind. Python has a module for handling decimal numbers more accurately, called decimal.
  1. Description
  2. Examples
  3. Choosing parameters
The format method of strings is a powerful way in Python to insert values of variables into text that is either printed or saved to a file. Formatting works by defining placeholders in strings (e.g. {:.2f}) for marking spots where the format method arguments will be placed. Example: "Interval between donkey's ears is {:.2f}".format(measurement).
Note: format is an older way for general string formatting. Using f strings is a more modern way. However, there are still uses for the good old format method too.
  1. Description
  2. Examples
Function is an independent part of a program that consists of the defining line (with the def statement) and the lines of code that defines the function's behavior. Functions are used to clarify program structure and to reduce redundancy. Functions communicate with each other and the main program through their parameters and return values. Variables (including parameters) defined inside a function cannot be accessed from outside the function. Likewise functions should not read values outside of their own scope.
  1. Description
  2. Examples
Function call is a procedure where the program's execution "jumps" to another location in the code - to the beginning of the function that is being called. When a function is called it is given a varying number of arguments - values that are assigned to parameters defined in corresponding positions in the function definition. A function's execution ends when a return statement is encountered or there are no more lines inside the function's code to execute. When this happens, the program's execution returns to the line where the function was called, and the function call itself is "replaced" by the function's return value.
In short function calls allow one part of the program to utilize another part - e.g. the main program can use a function, or a function can use another function.
  1. Description
  2. Examples
Functions are defined with the def statement which specifies the name of the function and the names its parameters. Choosing these is an essential part of writing generally useful functions. The name should describe what the function does accurately but shortly. Parameter names should be chosen so that it's easy to deduce what kinds of values they will take as arguments. The function's code is indented inside the def statement as its own block. A function code can - and often does - include multiple lines. It can also include further indentations (like control structures).
  1. Description
  2. Examples
Generator is a special type of object that works like a list in, for example, a for loop. However, it's not a series of values in memory like a list would be, but a special function that produces values in a lazy way, yielding a new one whenever it is called. Because of this it's not possible to show the "contents" of a generator, and it's not subscribable with indices. Generators are not included in beginner level courses.
  1. Description
  2. Esimerkit
  3. Tilasanakirjat
Globaali muuttuja (engl. global variable) on pääohjelman tasolla esitelty muuttuja, jota muokataan suoraan funktiossa tuomatta sitä funktion nimiavaruuteen parametrin kautta. Globaalien muuttujien käyttö on huonoa ohjelmointityyliä, ja niiden sijaan tietoa kuuluisikin kuljettaa funktioille argumentteina ja ottaa funktiolta vastaan paluuarvoina muutettuja arvoja. Näin tekemällä välttää niin kutsutun globaalin tilan, joka huonontaa koodin ymmärrettävyyttä.
Global scope encompasses all names (variables, functions etc.) that have been defined on the main program level. All names that belong to the global scope can be accessed from anywhere in the program code. However they can only be assigned new values in the main program level. In general functions should only use constants and other functions from the global scope. Main program variables should always be passed to functions through parameters.
A handler function is a function that has been connected to an event so that when the event occurs, the function is called. This often means that the handler is not called from within the same code file or module it was defined in, and instead it works as a callback. Handlers are often related to user interface and game libraries where the program's main loop is running inside the library and monitors events. In this scenario handlers are the actual application's means of implementing their functionality through events. Because the application's writer cannot influence how handlers are called, handler parameters and return values must match the requirements set by the library.
  1. Description
  2. Esimerkit
Hypystä (engl. jump) puhuttaessa tarkoitetaan ohjausrakenteen aiheuttamaa siirtymistä, jonka jälkeen ohjelman suoritus jatkuukin jostain muualta kuin seuraavalta koodiriviltä.
  1. Description
  2. Naming Conventions
Variables, functions, constants, modules and all kinds of things each have their own 'identifier - the part of the source code that's been assigned to mean that one particular thing. For instace if a programmer defines a variable width with the value 15 the name width can later be used to retrieve the variable's value. So the identifier can be thought of as a contract between the programmer and the Python interpreter about the meaning of a certain word in the code. Identifiers always belong to a namespace.
Indented code lines have blank characters in front of them, either spaces or tabs. The role of indentation in general is to organize code and improve its readability. However in Python indentation is also used as the syntax for separating code blocks from each other - all lines with the same indentation level belong to the same block. On this course we prefer spaces, and the width of one indentation level is 4 spaces. All reasonable text editors can be configured to insert spaces instead of the tab character when the tab key is pressed.
  1. Description
  2. Example
Index is an integer value that denotes the position of an item in an ordered collection (list, tuple, but also string!). Indices start from zero which makes the last index (collection length - 1). Index can also be thought of as distance from the beginning of the colection. Python supports negative indices where -1 points to the last item, -2 to second to last etc. Using an index to get an item from a collection is called subscription.
  1. Description
  2. Examples
When the index of a data structure, e.g. list, is used the act itself is called (index) subscription. The subscription is denoted with square braces, e.g. grades[0]. Subscription returns an item. Subscription outside the list causes an IndexError exception, and it's good to keep in mind that the last index of a list is its length - 1 (because indexing starts from zero). Index can also be negative - in this case counting starts from the end so that -1 is the last item of the list.
  1. Description
  2. Example
An infinite loop is a loop that does not have an end condition - the code inside it gets repeated "infinitely". Infinite loops do have uses in programming but they can also be caused unintentionally by a bug in the code. In Python infinite loops are usually "achieved" only by while loops.
  1. Description
  2. Examples
Input when used within the context of this course is a text-based command or answer to a question that's been requested from the program's user. It is prompted with the input function and will always be a string. When a program prompts for input the entire program stops until the user has given their input.
  1. Description
  2. Examples
Interface in general refers to a connection between two things, and in programming it particularly means the way in which two parts of a program are connected to each other. For instance we can talk about the interface of a function which refers to the way in which the function accepts information as parameters and returns information as its return value. Likewise libraries typically have an API (Application Programming Interface) that tells how the library's features are used. Humans are also connected to programs through interfaces, specifically user interfaces.
  1. Description
  2. Examples
Item or element is an individual value contained within a data structure. The term is most commonly used in the context of lists. In this context, items also have a position, index, that denotes its distance from the beginning of the list. Therefore the index of the first item in a list is 0.
Iteration is a concept related to loops. One iteration of a loop means executing the code inside the loop once.
  1. Description
  2. Examples
Key acts as an index for a dictionary. It can be used to look up a value from the dictionary. Each key corresponds to exactly one value. Keys are typically strings, but they can also be any immutable types like numbers or tuples.
  1. Description
  2. Examples
Keyword argument (kwarg) is used in function and method calls to assign arguments directly to parameter names. This is very often used with the format method: "Hello {name}".format(name="Hagrid"). Another common use case is with functions that have a whole lot of optional arguments and only some of them need to be given. Using keyword arguments can also make the code generally more readable, especially for arguments that are either True or False.
Kirjasto (engl. library) tai moduuli (engl. module) (kuten niitä Pythonissa virallisesti kutsutaan) on valmiiksi kirjoitettua koodia, jolla on oma rajattu tarkoituksensa. Tyypillisesti kirjasto sisältää ainakin nipun aihepiiriinsä kuuluvia funktioita, mutta voi sisältää muutakin (esim. luokkia tai vakioita). Esimerkiksi Turtle on kirjasto, jonka tarkoitus on tarjota helposti käytettäviä piirtofunktioita.
  1. Description
  2. Esimerkit
Kommentti (engl. comment) on kooditiedostossa olevaa tekstiä, joka ohitetaan kun koodia suoritetaan. Kussakin kielessä on oma tapansa sille miten rivi merkitään kommentiksi. Pythonissa se on #- eli risuaitamerkki (engl. hash character), jonka jälkeen riviltä löytyvän tekstin Python-tulkki ohittaa kokonaan. Kommenteilla voi selventää koodin lukijalle (tai itselleen) mitä koodissa tapahtuu. Yleensä kommentit on hyvä laittaa omille riveilleen kommentoitavan koodin yläpuolelle.
Ohjelman ja sen funktioiden toiminta kuvataan yleensä mieluiten dokumenttimerkkijonossa. Kommentteja käytetään enemmänkin välihuomioiden tekemiseen.
Toinen tapa käyttää kommentteja on tilapäisesti kommentoida rivejä pois esimerkiksi vaihtoehtoisen koodin testaamiseksi. Tällöin aiempaa koodia ei tarvitse poistaa – kätevää, jos myöhemmin osoittautuu, että sitä tarvitaan sittenkin.
Ohjelman käyttämät arvot ovat kovakoodattuja (engl. hard coded) silloin, kun ne esiintyvät literaaliarvoina – eli semmoisenaan – ohjelman lähdekoodissa sen sijaan, että ne selvitettäisiin ajonaikaisesti esimerkiksi kysymällä käyttäjältä tai lukemalla tiedostosta.
Käyttöliittymäelementti (engl. UI element, widget) on jokin (yleensä graafiselle) käyttöliittymälle ominainen komponentti, jonka kautta käyttäjän vuorovaikutus ohjelman kanssa on mahdollista. Tällaisia ovat esimerkiksi napit, valikot, liukusäätimet ynnä muut.
Lause (engl. statement) on ohjelmointikielessä nimitys yksittäiselle suoritettavalle asialle, joka on yleensä yksi koodirivi.
Lauseke (engl. expression) tarkoittaa ohjelmoinnissa evaluoitavaa yksikköä. Esimerkiksi 5 + 5 ja "aasi" != "apina" ovat lausekkeita, jotka evaluoituvat arvoiksi 10 ja True. Lauseke yksin ei muuta ohjelman tilaa mitenkään, ellei sillä ole sivuvaikutuksia. Sen sijaan lauseke vaikuttaa osana lausetta.
  1. Description
  2. Examples
List is an ordered collection of values, and in Python it's a true swiss army knife. A list can contain values of any types, and its size is not limited.
Values inside a list are called items or elements. Each item has its own designated spot inside the list, called index. Indices start from zero! In addition, list is a mutable type. The third material contains a lot of information about lists.
A list can also contain other lists. Such a construct can also be called a two-dimensional list. Of course it's possible to have more than two levels of nested lists, which increases the number of dimensions. These would be called multidimensional lists.
Literal (literal value) is a generic name for any values that are present in the code as such. I.e. the value is not assigned to a variable but has been written into the code itself. For instance in the statements x = 5 and print("donkey"), 5 and "donkey" respectively are literals. The term is used primarily for simple types: numbers, boolean values and strings.
Local variable is a variable that has been defined inside a limited scope, typically - and especially on this course - inside a function (including function parameters). A local variable cannot be accessed from the outside. In addition it gets destroyed when the scope it belongs in stops being relevant - usually when a function call ends.
Loop is a control structure that repeats the instructions contained within it either a certain number of times or until some condition is no longer met. Loops can be used to return program execution to a previous point, and they can also be used for processing large number of values. Python has two kinds of loops: for and while.
Loop Variable is a variable that's introduced in for loop declaration. This variable will receive each value in the sequence (e.g. list) that is being iterated over in the loop. Its value changes on each iteration. A simple example from the material: for animal in animals: where animal is the loop variable. If the sequence contains tuples (or lists), a for loop can also have multiple loop variables: for student, grade in grading:. Loop variables are not inside their own scope and must therefore be distinct from other names inside the same function's scope.
Main program is the part of the code where the real execution of the program starts. As a rule of thumb any statements and control structures that are attached to the left boundary are part of the main program. Main program is usually at the very end of a code file and usually inside if __name__ == "__main__": statement. However do not use this statement in the earlier exercises because then the checker cannot execute your program's main program.
Merkillä (engl. character) tarkoitetaan ohjelmoinnissa yksittäistä datana esiintyvää kirjainta, numeroa, välimerkkiä tai muuta vastaavaa symbolia. Pythonissa merkki edustaa pienintä merkkijonon yksittäistä palasta.
  1. Description
  2. Esimerkit
Merkkijono (engl. string) on tietotyyppi, joka sisältää tekstiä. Sitä käytetään erityisesti käyttäjän kanssa viestimiseen. Merkkijonojen sisältöä voidaan myös tallentaa tiedostoihin. Pythonissa merkkijono merkitään lainaus- tai heittomerkillä (esimerkiksi "aasi" tai 'aasi'). Suosimme ensimmäistä. Merkkijono voidaan merkitä myös kolmella merkillä jolloin se voi olla monirivinen – tätä käytetään erityisesti dokumenttimerkkijonojen (docstring) kanssa. Merkkijono on muuntumaton tietotyyppi – kaikki, mikä näennäisesti muokkaa merkkijonoa, tosiasiassa luo (ja palauttaa) siitä muutetun kopion.
  1. Description
  2. Examples
Method is a function that belongs to an object, i.e. it's one of the object's attributes. Methods are often used by objects to change their own state somehow, or derive another value from themselves. When a method is called it is prefixed with the object that ownds it: choice.lower(). Methods are occasionally called "member functions" as well.
Method Call is a similar process to function calls. As a significant different the target object is defined by prefixing method name with it whereas it would be given as an argument in a function call. In a typical method call an object operates on itself. For instance word.upper() is a method call that operates on the object referred to by the word variable.
Module is basically any Python code file. Although more commonly module is used as a synonym for library. Typically a module contains functions and potentially other (like constants and classes) things that are connected to a certain domain or use case. Large programs are also often split into modules so that each module focuses on one aspect of the program.
  1. Description
  2. Examples
Python objects can be divided into two types: mutable and immutable. Mutable objects can have their values changed during program execution e.g. as the result as a method call. The most common example of a mutable object is a list: hogwarts.append("Hufflepuff") changes a list named hogwarts by adding a new value to it. Any references to this list later in the program will access the contents that now include "Hufflepuff".
  1. Description
  2. Esimerkit
Pythonissa objektit erotellaan muuntuviin ja muuntumattomiin. Muuntumaton (engl. immutable) arvo on sellainen, jonka sisältö ei voi muuttua - kaikki operaatiot jotka näennäisesti muuttavat arvoa tosiasiassa luovat siitä uuden kopion, joka yleensä sijaitsee uudessa muistipaikassa. Esimerkiksi merkkijonot ovat tyypillinen muuntumaton tyyppi Pythonissa. Siksi merkkijonojen kanssa näkee yleensä jotain tällaista: valinta = valinta.lower()
Ohjelmointikielissä on oleellista ymmärtää määrittelyn (engl. definition) ero suorittamiseen. Määrittelemällä luodaan kuvauksia funktioista, muuttujista ja erilaisista tietorakenteista – tavallaan siis kerrotaan ohjelmointikieltä käyttäen, minkälainen jokin edellä mainituista asioista on, tai mitä sen kuuluisi tehdä. Pythonissa määrittelyn ja suorittamisen ero on helpoin ymmärtää funktioiden avulla. Funktiomäärittelyssä funktio vasta luodaan – ikään kuin tehtaalla koottu laite. Funktiota varsinaisesti käytetään – eli sen toiminnallisuus hyödynnetään funktiota varten määriteltyä koodia ajamalla – vasta funktiokutsun yhteydessä. Samaa vertausta käyttäen funktiokutsu vastaa siis sitä hetkeä, kun tehtaalta saapunut laite käynnistetään.
Nimikonflikti syntyy, jos useammalle kuin yhdelle arvolle koitetaan antaa sama nimi. Tällöin tapahtuu niin, että tuoreempi sijoitus jåä voimaan. Tästä seuraa yleensä ohjelman kaatavia virheitä, koska usein arvot ovat eri tyyppiä. Voi jopa käydä niin, että epämääräisesti nimetyn funktion päälle tallennetaan vahingossa saman niminen muuttuja.
Namespace is a group of names (variables, functions, constants etc.) that belong to the same context. For example the names inside a function (inside the function definition code block) form their own namespace: names inside the function are only accessible from within. There's also a global namespace which is the main program's namespace. Using normal import in a program creates a new namespace within that program that is accessible through the module's imported name - the names inside the module form their own namespace. See also: Scope.
Newline (line break, end of line, EOL), the "\n" character is a character that, when printed or written to a file produced a line break. If a string is inspected without printing it e.g. in the console, all line breaks are shown as "\n" characters.
  1. Description
  2. Esimerkit
Nimeämätön vakio tai taikaluku (engl. magic number) on koodissa esiintyvä literaaliarvo, jota ei selitetä millään tavalla. Hyvään ohjelmointityyliin kuuluu taikalukujen välttäminen. Oikea – itsedokumentoiva – tapa on nimetä koodissa esiintyvät vakiot muuttujiin, jolloin niiden muuttaminen onnistuu tarpeen tullen yhdestä paikasta yhdellä muutoksella, ja koodin lukijan on helpompi ymmärtää koodia.
  1. Description
  2. Syventävää nippelitietoa
Näppäimistökeskeytyksellä (engl. keyboard interruption) voi pakottaa jumiin jääneen ohjelman sammumaan. Sen saa aikaan painamalla Ctrl+C sen terminaalin ollessa auki, jossa ohjelma pyörii. Pythonissa näppäimistökeskeytyksen saa käsiteltyä kaappaamalla KeyboardInterrupt-poikkeuksen try-except-rakenteella.
Objekti (engl. object), joskus myös olio, on Pythonissa yleistä terminologiaa. Kutsumme objekteja pääasiassa arvoiksi alkeiskurssilla, mutta Pythonissa kaikkea voi käsitellä objekteina. Tämä tarkoittaa, että mihin tahansa voidaan viitata muuttujilla (esimerkiksi funktion voi sijoittaa muuttujaan). Tämän kurssin puitteissa objekti-termiä käytetään sellaisista arvoista joilla on metodeja.
Objektit nousevat merkittävämpään rooliin alkeista eteenpäin, erityisesti koodissa jossa käytetään luokkia.
Ohjelmointityyli (engl. programming style) on joukko ohjeita tai tapoja, joita ohjelmoija noudattaa koodia kirjoittaessaan. Näihin tapoihin lasketaan muun muassa sisennyksen syvyys, muuttujien ja funktioiden nimeämiskäytännöt, välilyöntien käyttö lauseissa sekä monet muut tyyliseikat. Ohjelmointityylejä on useita erilaisia, ja tällä kurssilla opetetaan noudattamaan tiettyjä tyyliin liittyviä sääntöjä.
Ominaisuus (attribute) liittyy objekteihin siten, että objekteilla voidaan sanoa olevan ominaisuuksia. Tällä kurssilla useimmat näistä ominaisuuksista ovat metodeja, mutta ne voivat olla myös arvoja. Objektin ominaisuutta käsitellään notaatiolla, jossa objektin nimen ja ominaisuuden nimen väliin tulee piste, esim: valinta.lower()-metodikutsussa valinta on objekti ja lower on ominaisuus.
  1. Description
  2. Examples
Opening mode is used for telling Python (and the operating system) how to open a file. A file can be opened for reading or writing. By default, if opening mode is not given, a file will be opened in reading mode "r". There are two writing modes:
  • "w", write, which overwrites anything that may have been in the file previously with the new content.
  • "a", append, which writes the contents to the end of an existing file instead
Both writing modes create the file if it did not exist previously.
Operand is the fancy name used in mathematics and programming for values that are used in an operation. E.g. 5 + 8 is an addition operation and its operands are 5 and 8. Operands can be thought of as the subjects of operations.
  1. Description
  2. Examples
Operation is a term used for anything carried out by an operator in the code. Mathematical operations are typical examples. An operation consists of an operator and one or two operands. For instance 5 + 5 is an operation.
Operator is a name for symbols that define an operation in mathematics and programming. Operators always appear with at least one operand, but often two. An example of an operator would be + symbol which denotes an addition operation.
An argument in a function call is an optional argument if its corresponding parameter has been given a default value. This means that it's possible to call the function without giving that argument. If there are multiple optional arguments for a function, they are often given using keyword arguments.
Parameter is a variable defined along with a function. They are variables that are assigned values from arguments when the function is called. In other words when values are transferred in a function call, they are called parameters from the function's point of view. E.g. in def prompt_input(question, error_msg): question and error_msg would be parameters. Parameters can also have a default value that will be used as its value if the matching argument is not given in a function call - this makes the argument optional.
Parametrization means expanding the use cases of a process by turning some of its values into variables. This way the same process can be repeated for multiple sets of values with different results. Mathematical functions are one kind of parametrization: all points represented by the function are produced by changing the value of a variable (e.g. x). In programming parametrization is quite concrete because usually a procedure is turned into a function. The function's parameters then define which values are not fixed and the function will behave differently with different parameters.
  1. Description
  2. Examples
Path is the location of a file or folder on the hard drive. A path can be absolute or relative. Absolute path includes every folder from the target all the to the root (e.g. in Windows the root is the drive letter, like C:) whereas relative only includes folders up to the active folder (i.e. the folder where the program was started in). Path is usually presented in programming languages as a string, and path parts are separated with slashes /. When forming path inside code, it's best to use the join function from the os.path module.
  1. Description
  2. Additional formatting
Placeholder is by general definition a way to mark a spot that will be replaced by something else later. In this course they are primarily used with string formatting. A placeholder within an formatting string is marked with curly braces (f"Hi {name}"). Placeholders in strings can also contain additional formatting specifiers like setting the number of decimals to show (f"Donkeys have {average:.2f} legs on average"). When a placeholder is resolved, it is replaced by the value of the variable or statement inside the curly braces.
  1. Description
  2. try-except-else-finally
Poikkeusten käsittely (engl. exception handling) on ohjelmointikieleen sisäänrakennettu keino ohjelmoijalle reagoida poikkeuksiin. Pythonissa poikkeusten käsittely onnistuu try-except-rakenteella, jossa sekä try: että except: aloittavat omat lohkonsa; try-lohkon alle kirjoitetaan se koodi, joka mahdollisesti aiheuttaa jonkun tietyn poikkeuksen ja except-lohkon alle taas se koodi, joka suoritetaan siinä tapauksessa, että kyseinen poikkeus tapahtuu. Joissain muissa ohjelmointikielissä except-avainsanan sijaan käytetään avainsanaa catch, minkä takia yleisesti puhutaan poikkeusten kiinni ottamisesta.
Precedence, of math fame, defines in which order various operations in a statement are resolved.
result = 10 + 2 * (2 + 3)
The result of this statement is 20 because the sum of 2 and 3 is resolved first, followed by multiplying the result by 2, and finally adding the multiplication result to 10. In this example the highest precedence is held by the operation in braces, followed by multiplication, and then finally addition.
Precedence defines the execution order of instructions or operations on a line of code. Operations of different type have different precedence in execution order. These can be found from the link below. Operations with same precedence are executed from left to right. Like in mathematics, the order can be changed by using parentheses.
  1. Description
  2. Examples
Printing is somewhat different in programming context - although not really that far removed - from combining paper and ink to pages. In context of computer programs it usually means producing text on the screen, especially to a terminal. Python has a function for this purpose: print(...) that prints its argument(s) to the terminal.
Programming problem is the goal of a programming task. It is therefore some sort of a need that has been recognized and a program is coded to fulfill that need. The need can be e.g. automatization of a task, creating a web site or just making a fun game.
  1. Description
  2. Examples
Interactive Python interpreter or Python console as we like to call it is a program that executes Python code lines as they are written into it. It shows the return value of the line if any exists (e.g. the result of a mathematical operation). On this course we use IPython instead of the vanilla Python console. After installation you can start IPython by typing ipython to the terminal.
Python interpretetr is a program that transforms Python code into instructions to the computer's processor. It's responsible for executing both code files and individual lines in the Python console. The word can also be used to mean Python console though, so be careful.
  1. Description
  2. Examples
Recursion is a common programming term that refers to a function calling itself. Recursion is a function-based way to create repetition in the code where the function gives itself new arguments and handles its own return values. Recursion is handy e.g. when navigating tree-like structures - one "branch" is handled at a time, and then recursion is used to handle branches branching out from that branch, and so on. Recursion is not very widely used in Python. One reason is the recursion depth limit which restricts how many times a function can call itself.
Referring is the method in which a variable is connected to its value. The target of the reference is the computer's memory and the variable itself - under the hood - contains an address where from memory the value can be found.
Relative path is an operating system concept that indicates the path to a file or folder from the current folder. Relative paths do not care what kind of a garden maze of folders exists between the disk drive root and the current path. For this reason relative paths are usually used to refer to a program's own sub folders. This allows the program to be moved to another location without updating any paths in the code.
  1. Description
  2. Examples
Return is a process that happens when a function's execution ends. Typically the value(s) returned by the function are defined inside the function with a return statement. In the code that calls the function, the return value will replace the function call and can therefore be assigned to a variable or passed on to another function.
Return value is the value (or values) that a function returns when its execution ends - the function's result. Functions in Python can have multiple return values. When reading code you can regard return value as something that will replace the function call when the function execution has ended. A return value is defined inside a function with the return statement. E.g. in return True there is one return value: the literal boolean value True.
Sapluuna (engl. template) on muotti esimerkiksi tekstille, joka käyttäjälle halutaan näyttää, mutta joka ei semmoisenaan ole vielä valmis. Sapluunasta siis puuttuu tietoa, joka on tarkoitus saada sapluunan paikanpitimien tilalle.
Kurssilla yleisin sapluuna on merkkijono, jossa on paikanpitimiä format-metodia varten.
  1. Description
  2. Examples
Scope is a concept related to the visibility of names (variable, function etc.) in certain parts of the program. For instance within a function block any names defined inside the function can be used because they belong to the same scope. Other functions cannot access these names because they belong to a different scope. Names in the global (main program) scope can be accessed from anywhere in the code.
  1. Description
  2. Examples
Separator is a term related to strings and text files. It means a specific character that is meant for indicating a split inside a string when it is read into the program. For instance, if a string contains values that will be parsed into a list, the separator is the character than indicates where one part ends and the next one begins. The split method is often used in these situations - the method can use a specific separator to split a string into a list.
A sequence is any value in Python that is a series of things - for instance, string, list and tuple are all sequences.
  1. Description
  2. Examples
Slicing is the act of taking a new sub-sequence out from an existing sequence (usually list, but sometimes also string). The result of slicing is a value with the same type that's a copy of the selected part in the original sequence. The selection is done by choosing start and end indices. Both are optional. A slice is written as follows: page = collection[5:10] - this would make a slice including indices 5...9. The number on the right side of the colon in a slice is the first index that is not included in the result!
Slicing never causes an IndexError.
Solution model is an abstract construct developed by a programmer regarding how the solution to a programming problem works. It's not code yet, but it should be explicit and dividable into distinctive steps so that it can be turned into a program. Solution models can be sketched inside one's mind, by using paper and by trying this out in the Python console.
Source code or code means text that has been written with a programming language.
State, as the name suggets, referes to the program's current state. In practice state covers everything belonging to the program's state space like variable values, data in files, and where the code execution is currently at. A guaranteed way to make spaghetti code that's beyond repair is to use the global state - a crime that's perpetrated by functions that use global variables.
Later, on courses that go more formally into programming concepts, you'll learn of things like state machines, as well as stateless and stateful programs.
  1. Description
  2. Examples
Stub function is a function that's been defined properly with all the parameters etc. but has no content in it. They are typically put into the program code when planning its overall structure. Doing so allows the functions to be called elsewhere in the code while the function isn't fully implemented yet. The contents of a stub function usually come down to just pass, an informative print, or returning some placeholder default value. In larger projects stub functions sometimes are set to raise a NotImplementedError exception which makes it easy to locate the function that's not ready yet.
Syntax is the grammar of code. It defines what kind of text counts as valid Python. If code doesn't conform to the correct syntax, it cannot be executed. Syntax also informs a programmer about the correct formatting for each stement in the programming language.
Syntax error is an exception that happens when the Python interpreter inspects a code file before executing it and notices something broken in there, i.e. code that is written incorrectly. A code with syntax errors is not run at all.
One common syntax error is unbalanced parentheses. This results in a strange error message in the sense that Python reports the next line as the cause of the error. Remember to check previous lines as well when you receive strange syntax errors!
Takaisinkutsu (engl. callback) on yleinen ohjelmoinnissa käytetty menetelmä, jossa funktio ottaa parametrin kautta vastaan funktion kutsuttavakseen heti (synkroniset takaisinkutsut) tai joskus tulevaisuudessa (asynkroniset takaisinkutsut). Nimensä menetelmä on saanut soittopyynnöstä: kutsuttavaa funktiota, jolle jokin funktio välitetään argumenttina, ”pyydetään” kutsumaan tätä annettua funktiota. Pythonissa listojen sort()-metodin key-parametri on esimerkki callback-funktioiden käytöstä. Usein käyttöliittymiä toteutettaessa käyttöliittymäelementteihin kytketään callback-funktioita.
Terminal, command line, command prompt and shell' are different names to the text based interace of an operating system. It is used for text-based operating system commands and for running terminal programs. On this course we mostly move around with cd (change directory) and use ipython command to run code files and start the Python console.
  • In Windows you can open the terminal by typing cmd to the start menu search
  • In Mac OS X you can start the terminal by typing terminal to Finder
  • In Linux you can open the terminal from the desktop by pressing Ctrl + Alt + T or by typing terminal to the search
Testaamalla eli kokeilemalla (engl. test) selvitetään, toimivatko hartaasti näppäillyt koodirivit halutulla tavalla. Testejä suorittamalla siis etsitään koodista mahdollisia ohjelmointivirheitä. Ohjelmien testaaminen on jopa niin olennaista, että joidenkin alan työntekijöiden tehtävänä on ainoastaan automatisoitujen testien ohjelmointi. Lovelace-järjestelmän tarkistimet testaavat järjestelmään lähetetyt koodit.
Generally text file is any file that can be read with a text editor. In this course's context we use text file to refer to files that are handled as text inside Python. We do this to separate them from code files that are run with Python. Text files are used in this course to store data between runs of the program.
Tosi (engl. true) on toinen kahdesta mahdollisesta totuusarvosta ja toisen, eli epätoden, vastakohta. Sitä voidaan pitää lopputuloksena loogisissa ja vertailuoperaatorioissa, jotka pitävät paikkansa. Esimerkiksi vertailuoperaatio 5 > 4 pitää paikkansa, joten kyseinen operaatio evaluoituu todeksi. Pythonissa totta merkitään avainsanalla True.
  1. Description
  2. Esimerkit
Traceback is the process of tracing an error back to its source. When an exception occurs the Python interpreter prints an error message that includes a traceback. It's presented as a stack of function calls where the last one is the funtion where the exception occurred. They are also called stacktrace for this reason. For example if the main program calls the funcion f which in turn calls function g where the exception occurs, the stack would be
main programfg.
  1. Description
  2. Examples
Tuple is a co-called frozen list. It's an ordered collection of values like a list but it's an immutable object. A tuple can't be changed. They can only be created, and read. Usually a tuple is delimited with normal braces: "#!python3 (1, 2, 3) but actually this is a tuple even without them: 1, 2, 3.
Unlike lists, tuples can be used as dictionary keys.
  1. Description
  2. Examples
Type conversion (also type casting and type coercion) means changing the type of a variable or literal value to another one. In Python this is commonly done when a number is requested from the user and it is returned as a string. In practice this can be done with e.g. int("123") or float("3.14"). In some cases Python performs type conversion automatically, usually when mathing with floats and integers.
Tyylisäännöt ovat kokoelma suosituksia, joiden mukaan koodia tulisi kirjoittaa. Kullakin kielellä on yleensä omansa. Tyylisääntöjen rikkominen ei varsinaisesti riko ohjelmaa, mutta tyylisääntöjen mukainen koodi on miellyttävämpää lukea ja usein tästä johtuen myös helpompi korjata. Tällä kurssilla seurataan Pythonin virallista tyylistandardia erityisesti tekstikenttätehtävissä. Myös tiedostotehtävissä on koodin laadun tarkistus, jossa käytetään PyLint-ohjelmaa.
  1. Description
  2. Esimerkit
Tyyppi (engl. type) on arvon ominaisuus – jokainen arvo edustaa aina jotain tiettyä tyyppiä. Tyypin tarkoitus on siis kertoa, minkälaisesta arvosta on kyse. Käytännössä tästä seuraa myös se, mitä operaatioita arvoilla voi tehdä, ja mitä metodeja niiltä löytyy. Funktiot on myös miltei aina toteutettu siten, että niille syötettävien argumenttien täytyy olla tietyntyyppisiä, jotta funktio voisi toimia. Tyypit ovat yksi ohjelmoinnin keskeisimmistä käsitteistä.
Pythonissa arvojen sopiminen koodista löytyviin operaatioihin tarkistetaan tilannekohtaisesti näiden arvon ominaisuuksien perusteella – ei siis suoraan itse tyyppiä tarkastamalla. Esimerkiksi useimmissa tapauksissa kokonaisluku ja liukuluku kelpaavat molemmat, mutta on myös tapauksia, joissa näin ei ole (esimerkiksi merkkijonoa ei voi kertoa liukuluvulla).
Tällä kurssilla tyypillisiä tyyppejä ovat kokonaisluku (int), liukuluku (float), merkkijono (str), lista (list), totuusarvo (bool) ja monikko (tuple). Myös funktioilla on oma tyyppinsä!
User Interface (UI) is the interface between a program and its user (typically human). In a simple text based UI input function calls are used to prompt things from the user and print calls can be used to display instructions and results.
Many programs intended for end users (consumers) typically offer a graphical user interface (GUI). These typically involve icons, popup menus and other elements that can be poked with by mouse or touch screen. On this course we will take a very shallow stab at graphical user interfaces in the final project.
A simplified way to describe variable is to think of it as an information storage - it contains something. This expression is often used in speech even though it's not entirely accurate. The more accurate description is that a Python variable is a reference to a value. It's a connection between the variable's human-readable name and a value that's stored in the computer's memory. So the variable in fact doesn't contain the value, it just contains information about where it is.
  1. Description
  2. Examples
The break keyword is a special instruction that is used in loops. It interrupts the loop's execution immediately, and code execution continues from the first line after the loop. If the loop had an else branch, it is not entered.
  1. Description
  2. Examples
continue is the other keyword related to loops (the first one being break). Unlike break which interrupts the entire loop, continue only interrupts the current iteration - execution continues from the next iteration. Note that this keyword is only needed in situations where part of the iteration is to be skipped. There's no need to put continue to the end of the loop iteration.
  1. Description
  2. Examples
enumerate is builtin function that produces a generator-like object in Python. Its primary use is in for loops when the code needs to access the items' indices in addition to the items themselves. The enumerate object produces tuples where the first item is the original item's index and the second item is the original item itself. Use example: for i, character in enumerate(moomin_valley):.
f(ormat) string is a special string that is used for inserting values from variables or simple clauses inside a piece of text. This is also called string interpolation in programming terminology. This kind of a string is marked by prefixing it with a lowercase f. You can include placeholders inside the string by using curly braces, and writing variable names or clauses inside them.
Example: f"Interval between donkey's ears is {measurement:.2f} inches" (assuming that a variable named measurement has been definied previously)
  1. Description
  2. Examples
In Python for is one of the two loop types. It's designated for iterating through data structures. It is used especially with lists. In general, for loops are used when it's possible to determine in advance how many iterations the loop must do. In addition to iterating through structures, for loop is therefore used for doing a certain number of iterations (e.g. 10 iterations). For loop declarion looks like for item in collection: where item would be the name of the loop variable, and collection would be the data structure that is being iterated over.
  1. Description
  2. Examples
In Python modules are "activated" by import statements. In normal use (e.g. import math) the statement makes a new namespace accessible through the module name. Functions from the imported module can be accessed through its name. It's also possible to directly import some specific names from a module with a from-import statement: from math import ceil. Modules can also be renamed on import: import math as m.
  1. Description
  2. Esimerkit
Silmukoista while pohjautuu toistoon ehdon tarkastelun kautta - silmukan sisällä olevaa koodilohkoa suoritetaan niin kauan kuin silmukalle annettu ehto on tosi. Ehto määritetään samalla tavalla kuin ehtolauseissa, esim: while summa < 21. While-silmukat soveltuvat parhaiten sellaisiin tilanteisiin, joissa ei voida etukäteen selvittää montako toistoa tarvitaan - erityisesti syötteiden kysyminen käyttäjältä on tällainen tilanne.
  1. Description
  2. Examples
In Python with is a somewhat exception keyword in that it's not a control flow structure or definition of a new thing. On this course it's primarily used when opening files, e.g. with open("donkey.txt") as somefile:. All read or write operations on the file are carried out inside the with statement. When the with statement ends, Python automatically takes care of closing files opened in the with statement.