Termbank
  1. A
    1. Absolute Path
    2. Ajonaikainen
      konseptit
    3. Alustaminen
      muuttujat arvot
    4. Argumentti
      funktiot arvot
    5. Arvo
      arvot
    6. Assignment
      muuttujat arvot
    7. Assignment Operator
      muuttujat arvot operaattorit
    8. Attribute
      objektit
    9. Attribuutti
      Attribute
    10. Avainsana
      nimet
    11. Avausmoodi
      tiedostot
    12. Ajaminen
      Execution
    13. Aliohjelma
      Function
  2. B
    1. Boolean
      ohjausrakenteet tyypit
    2. Boolean Operator
      ohjausrakenteet
    3. Boolen operaattori
      Boolean Operator
    4. Branch
      ehtorakenteet try-rakenteet
    5. Builtin Function
      funktiot
    6. Bugi
      Ohjelmointivirhe
    7. break
      avainsanat toistorakenteet
  3. C
    1. Callback
      funktiot
    2. Carriage return
      merkkijonot tiedostot pakeneminen windows
    3. Code Block
      funktiot ohjausrakenteet
    4. Code File
      konseptit
    5. Comparison Operator
      operaattorit ohjausrakenteet
    6. Comparison Value
    7. Condition
      ohjausrakenteet
    8. Conditional Statement
      ohjausrakenteet
    9. Conditional Structure
    10. Constant
      muuttujat arvot
    11. Control Structure
      ehtorakenteet toistorakenteet try-rakenteet
    12. Ctrl + C
      Näppäimistökeskeytys
    13. Callback
      Takaisinkutsu
    14. continue
      avainsanat toistorakenteet
  4. D
    1. Data
    2. Data Structure
      konseptit listat sanakirjat
    3. Debugging
    4. Default Value
      funktiot arvot parametrit
    5. Dictionary
      tietorakenteet
    6. Docstring
      dokumentointi
  5. E
    1. Epätosi
      arvot
    2. Erotin
      merkkijonot listat tiedostot syöte
    3. Error Message
      ongelmanratkaisu
    4. Escape
      merkkijonot
    5. Evaluointi
      arvot lausekkeet
    6. Exception
      poikkeukset ohjaurakenteet
    7. Execution
      konseptit lausekkeet
    8. Elementti
      Item
    9. enumerate
      toistorakenteet listat
  6. F
    1. False
      Epätosi
    2. File Extension
      tiedostot
    3. Filename
      tiedostot merkkijonot
    4. Float
      arvot tyypit
    5. Format
      merkkijonot tulostus
    6. Function
      funktiot
    7. Function Call
      funktiot lauseet
    8. Function Definition
    9. for
  7. G
    1. Generator
      objektit toistorakenteet
    2. Globaali muuttuja
      muuttujat arvot
    3. Global Scope
  8. H
    1. Hyppy
      ohjausrakenteet
    2. Hardkoodaus
      Kovakoodaus
  9. I
    1. if-lause
      Conditional Statement
    2. if-rakenne
      Conditional Structure
    3. Identifier
      muuttujat funktiot
    4. Indentation
      konseptit
    5. Index
      listat arvot
    6. Index Subscription
      listat arvot
    7. Infinite Loop
      toistorakenteet
    8. Input
      konseptit merkkijonot
    9. Interface
      konseptit funktiot moduulit
    10. Item
      listat arvot
    11. Iteration
      toistorakenteet
    12. import
      moduulit
  10. J
    1. Jäsenfunktio
      Metodi
  11. K
    1. Koodilohko
      Code Block
    2. Kutsu
      Function Call
    3. Key
      arvot sanakirjat
    4. Keyword Argument
      funktiot
    5. Kirjasto
      moduulit
    6. Komentoriviargumentti
      terminaali
    7. Kommentti
      dokumentointi virheenetsintä
    8. Kovakoodaus
      arvot
    9. Käsittelijä
      funktiot konseptit
    10. Käyttöliittymäelementti
    11. KeyboardInterrupt
      Näppäimistökeskeytys
    12. Koodi
      Source Code
    13. Komentorivi
      Terminal
    14. Komentokehote
      Terminal
    15. Kahva
      Tiedostokahva
  12. L
    1. Lause
      konseptit
    2. Lauseke
      konseptit
    3. List
    4. Literal
      arvot
    5. Local Variable
    6. Loop
      ohjausrakenteet
    7. Loop Variable
      toistorakenteet muuttujat
  13. M
    1. Muotoilu
      Format
    2. Main Program
      konseptit
    3. Merkki
    4. Merkkijono
      arvot tyypit
    5. Method Call
      lausekkeet objektit
    6. Metodi
      objektit funktiot
    7. Module
    8. Mutable
      konseptit listat arvot
    9. Muuntumaton
      konseptit merkkijonot arvot
    10. Määrittely
      konseptit
  14. N
    1. Name Conflict
    2. Namespace
      konseptit funktiot moduulit
    3. Nimeämätön vakio
      vakiot arvot
    4. Näppäimistökeskeytys
      poikkeukset
  15. O
    1. Objekti
      konseptit
    2. Olio
      Objekti
    3. Ohjelmointityyli
    4. Ohjelmointivirhe
      ongelmanratkaisu
    5. Ominaisuus
      objektit
    6. Operand
    7. Operation
      lausekkeet
    8. Operator
    9. Optional Argument
      funktiot arvot parametrit
  16. P
    1. Paikanpidin
      merkkijonot tulostus
    2. Parameter
      funktiot
    3. Parametrization
    4. Poikkeus
      ongelmanratkaisu try-rakenteet
    5. Poikkeusten käsittely
      ohjausrakenteet poikkeukset
    6. Polku
    7. Precedence
    8. Printing
      konseptit merkkijonot
    9. Programming Problem
      ongelmanratkaisu
    10. Python Console
      työkalut
    11. Python Interpreter
      työkalut
    12. Presedenssi
      Sidontajärjestys
  17. R
    1. Referring
      muuttujat arvot objektit
    2. Rekursio
      funktiot konseptit
    3. Relative Path
    4. Return
      funktiot arvot
    5. Return Value
    6. Rivinvaihtomerkki
      merkkijonot tiedostot
  18. S
    1. Silmukka
      Loop
    2. Sapluuna
      merkkijonot konseptit
    3. Scope
      lohkot konseptit
    4. Sequence
      tietorakenteet toistorakenteet konseptit
    5. Sidontajärjestys
      konseptit lausekkeet
    6. Suoritusjärjestys
      Sidontajärjestys
    7. Slicing
      listat
    8. Solution Model
      ongelmanratkaisu
    9. Source Code
      konseptit
    10. Stub
      funktiot ongelmanratkaisu
    11. Syntaksi
      konseptit
    12. Syntax Error
      poikkeukset
    13. Stacktrace
      Traceback
  19. T
    1. Taikaluku
      Nimeämätön vakio
    2. try-rakenne
      Poikkeusten käsittely
    3. Takaisinkutsu
      funktiot
    4. Tallennusformaatti
      tiedostot merkkijonot
    5. Tapahtuma
      konseptit
    6. Tekstitiedosto
      tiedostot
    7. Terminal
      työkalut
    8. Testaaminen
      konseptit ongelmanratkaisu
    9. Tiedostokahva
      tiedostot objektit
    10. Tila
      konseptit
    11. Tosi
      arvot
    12. True
      Tosi
    13. Traceback
      ongelmanratkaisu
    14. Tuple
      tietorakenteet listat
    15. Type Conversion
      tyypit arvot funktiot
    16. Tyylisääntö
    17. Tyyppi
      arvot konseptit
  20. U
    1. User Interface
      konseptit
  21. V
    1. Variable
      konseptit arvot
  22. W
    1. while
      toistorakenteet
    2. with
      tiedostot
Completed: / exercises

2. Material: Transformations and Crossroads

Signs of a Storm

In this material we're going to turn Python from a calculator into a typewriter. We'll also learn more advanced communication with the user. Our programs start to react to what the user does. The revolution of machines is just around the corner.
This material continues with essential programming concepts: conditional statements and strings, the latter of which was visited briefly earlier. In line with the typewriter theme we've also managed to fit in dictionaries. These tools could already be used for something epic like a text-based adventure game. We're not going to do that though because it would involve writing much more text than code. What we are going to do, is to go through some common scenarios encountered in programming.
Most real programs have some kind of a menu where the user can choose what to do with the program. Most programs don't do just one thing, they do a bunch of things related to each other. As an example image processing programs contain all sorts of tools and features that all share a common ground: they have something to do with manipulating digital images. Choices form the overarching theme for this material. On the one hand we're going to let the user know what options they have; on the other hand we need to provide the user with means to make a choice. We've ran out of hands but there's also the matter of how computers can be instructed to perform the selected task.

Trial and Error

Learning goals: This section covers handling of exceptions in code. You'll learn a new structure that is intended for this purpose.
At the end of the last material we threatened to let less perfect hands poke our beautiful programs. Earlier we just hand-waved over a rather important matter: what actually happens in the program if we try to convert something to a number when it doesn't look like one? Something like this can happen simply because a smart-ass user tries to input donkey as a number. Let's go through this using the ball calculator from exercise 1. You can find the code below.
ball.py
Enter ball circumference: 23 cm
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/media/sf_virtualshare/OA/code/H1/ball.py in <module>
     16     return area, volume
     17 
---> 18 measurement = float(input("Enter ball circumference: "))
     19 ball_area, ball_volume = calculate_ball_properties(measurement)
     20 print("Volume:", round(ball_volume, 4))

ValueError: could not convert string to float: '23 cm'
The
string
that the user provided does not look like a number because it has a unit at the end. As much is told by the last line of ther
error message
. Because error messages are roughly as terrifying as Necronomicon for mere mortals, it's usually best to protect them from seeing them and use friendly notifications instead. We'll focus on this sanity preservation next.

The Philosophy of Exceptions

Because we cannot know what users try to do to our program with their
inputs
the program has to have some means of dealing with exceptions. Python, like most other programming languages, has a structure for dealing with this: we usually talk about a process called
exception
handling.
Image source 1
The basic idea is that we attempt to execute all code in a "business as usual" fashion but at the same time make some precautions at spots where we know things can go wrong. There's two sides to this: first of all we need to know what even are the potential issues; second, we need to instruct the program about how to deal with them.
When attempting to input letters into the program we're greeted with a harsh ValueError
message
. There's no magic way to find out all problem scenarios. You just need to try everything you can come up with and hope the users don't have more imagination than you. Good luck with that by the way.
Usually various problem scenarios come up during a program's development, and often this leads to rewriting some parts of the code. It's not uncommon for new errors to be found once the program is completed either. Just look at how many games have bugs on release just because quality assurance didn't have the time and imagination to match that of thousands or millions of players - not to mention speedrunners who try to deliberately break games just to complete them faster.
With our program here we do already know one potential problem scenario: when the user
inputs
something that doesn't convert to a number. We can look at
exception
handling through this example. One good way to deal with this is to "translate" the
error message
to language that is easier for laymen to understand. E.g. the program could just say "Input must be a plain number." After this the program can just end and the user can run it again, and perhaps be a bit wiser next time. It's not ideal but we can't do better until later.

Exceptional Structure

As we've learned, an
exception
can occur in the program when the user inputs a
string
that the float
function
cannot convert. We want to give the user a friendly notification by printing: "Input must be a plain number." Implementing this behavior is built around three
keywords
: try, except, and else. Together these three form a new special structure. The last of the three is not a mandatory part of the structure but often good to have. This structure defines:
  1. which lines we expect to produce the exception (try)
  2. which exceptions should be handled, and what to do when they occur (except)
  3. how to proceed when nothing goes wrong (else)
In our case the answers would be:
  1. the input line
  2. ValueError, inform the user about invalid input
  3. execute rest of the program like before
These three are placed inside the structure using indentations:
try:
    measurement = float(input("Enter ball circumference: "))
except ValueError:
    print("Input must be a plain number.")
else:
    ball_area, ball_volume = calculate_ball_properties(measurement)
    print("Volume:", round(ball_volume, 4))
    print("Surface area:", round(ball_area, 4))
The first part of this structure is the try
branch
which is started with the try
keyword
and a colon. The code line where we know the
exception
occurs in is placed inside this
block
,
indented
.
The next part is the except branch. In most cases except should be told which exception(s) it should handle. This is done by putting the exception's name after the keyword, before the colon at the end. Inside the branch, in its own block, is code that is executed when the exception occurs. In this case it's the line that prints the notification to the user.
The last part is the else
branch
which contains basically the rest of the code,
indented
to its own block. The code in this block is only executed if the code inside the try branch goes through without issues. The animations below show how program execution proceeds through this try-except-else structure and after it.
Image source 2
Not all
exceptions
are intended to be caught. Most importantly, exception handling should not cover problems arising from bad code - this problems should be fixed with better design. Exceptions that are often related to these kinds of problems include TypeError and NameError. NameError was encountered in the last material when we tried to access a
function's
local name
from the
main program
. It means we're trying to access a variable that has not been defined. This can be due to a typing error but can also result from poor branching: the variable is defined in a
branch
that is not always entered. For instance if we tried to leave out the else part from the latest example:
try:
    measurement = float(input("Enter ball circumference: "))
except ValueError:
    print("Input must be a plain number.")
ball_area, ball_volume = calculate_ball_properties(measurement)
print("Volume:", round(ball_volume, 4))
print("Surface area:", round(ball_area, 4))
If the user now gives an invalid
input
the notification does get printed. However, the program execution does not end, and instead continues to the first line outside the try structure. This particular line tries to retrieve the ball's properties using its measured circumference from the measurement
variable
as an argument. Problem is, this variable was never defined and the result is NameError. The variable was not defined because the execution of the line inside the try statement stops immediately when the float
function
causes an
exception
. The real problem in this case is that all three last lines should be inside the else branch because they can only be executed if, and only if the measurement variable is successfully created.

Computational Violence

Programs can and will get stuck for wide variety of reasons. Users need to have ways to interrupt them by force, preferably without shutting down the entire computer. For terminal programs this is usually achieved with a keyboard interrupt. In this assignment we'll learn how to do a keyboard interrupt and what it causes in a program.
Learning goals: How to interrupt a running program and what is the name of the
exception
it causes in the program.
Introduction:
Type the following two lines into the
console
and hammer the enter key unless no more ...: characters pop up:
In [1]: while True:
   ...:     pass
   ...:  
   ...: 
These two lines cause an
infinite loop
where the computer is stuck forever doing absolutely nothing very meticulously. Interrupt the loop by pressing Ctrl + C.
Answer Specification:
The answer to this task is the name of the exception that's shown in the terminal when the program dies. Copy the name to the answer box.
Exception name here please.
Warning: You have not logged in. You cannot answer.

The Other Cheek - The Program

This exercise introduces a very common main program structure where the keyboard interrupt from the previous task is handled without a fit. In other words we're going to make a program that just says "So long, and thanks for all the fish" instead of exploding into a wall of error text when punched with an interrupt.
Learning goals: Writing a basic
exception
handling structure and learning a common
main program
structure.
Before You Begin:
In order for you to test the main program code in a meaningful way, the code file needs to have a
function
that can be interrupted with Ctrl + C. A simple function that prompts the user for
input
and prints it will do the job.
def main():
    print(input(": "))
If we were making a real program there would be the program's main logic in place of the simple input line. Place this function to the beginning of the file and write your solution after it.
Main Program:
Your goal is to write a simple try-except structure where you
call
the main function inside the try
branch
. The except branch should catch the exception from the last exercise. If this exception is indeed encountered the program should print "So long, and thanks for all the fish". This program does not need an else branch in the structure.
Warning: You have not logged in. You cannot answer.

Fateful Choices

As we promised earlier, any program of significant size has some kind of a menu. To proceed we probably need to start making one. Let's dive into one of the most profound mysteries in the world: US customary units that are void of any discernible logic. Our goal is to make a program that converts these distance-between-a-happy-donkey's-ears-at-midsummer types of units into proper SI units.
In other words, we're making a program that can convert the following units:
This will be first somewhat complex program in this course. This means it's the first time we can really think about the best way to implement it. We can do the conversion calculations easy enough, but we also need to decide how the program is used.
Learning goals: In this section we're going to learn how a program's flow can be controlled based on user's inputs. Conditional structures will serve a central role in this endeavor. After this section you will know what they are and how they can be used for implementing menu structures. You will also learn a statement that does nothing, and how it's actually useful when drafting the program's function structure.
Image source 3

A World of Choices

An integral question when it comes to designing how to implement our program is: how is it going to know what the user wants? In this particular case we need a way to find out what unit the user wants to convert. At the moment we can only read text
inputs
from the user which leaves us with two options: ask the user which unit they want to convert, or ask them to include the unit with the value input and we interpret it from there (e.g. "5 oz"). The latter option would probably be nicer to use. However its implementation is going to need more than we're ready to chew in this material. Let's settle with the solution where the unit is selected with a separate input.
Since there's a bunch of units there, we're also going to split them into categories: length, mass, volume and temperature. This results in a menu structure that has two levels: first the users selects a category, and then they select a unit within that category. Finally they enter the value they want to convert. To put it as a diagram, the program branches in the following way:
Ohjelman suunniteltu haarautuminen eri toimintoihin.
Because we only have one (but all the more confusing) temperature unit, the menu doesn't have a second level in that case. After doing this initial design it might be high time to learn how to actually make a program's execution branch. In programming, conditional structures serve this purpose.

Unconditionally Maybe

Conditional structure
is, as the name suggests, a structure made of conditions, and the fulfilment of each condition leads to something happening.
Conditional statements
are largely formed like they would be in natural languages: "if deadline is at midnight, now is the time to code". Earlier we introduced the try structure that is in its own way a special case of a conditional structure: "if making coffee fails, make tea instead, otherwise drink coffee" where "making coffee" would be the try
branch
, "make tea instead" would be the except branch, and "drink coffee" would be the else branch. In this structure the so-called conditions are
exceptions
raised by Python whereas actual conditional statements usually assess the
values
of
variables
or
statements
in one way or another. For instance we can check whether the user's
input
is identical with the "length"
string
. As code:
if choice == "length":
In this example choice is a variable that refers to the user's input. On this line the
condition
itself is choice == "length" which is the statement that is being evaluated. == is an
operator
that compares two values for equality. It returns a
boolean value
which is a type that only has two
literal values
: True and False.
In programming, if is a
keyword
that evaluates the truthfulness of its associated condition: if the condition is True (or equivalent) the code defined under the if
branch
is executed; if the condition is False (or equivalent) that code is not executed. In either case, code execution eventually continues from the first line that is outside the conditional structure (i.e. after it).
The following animations illustrate how this works. In the code example, negative numbers and zero for item counts are converted to one before adding to the catalog.
There's two important points in these animations: first, the condition in each
conditional statement
is always reduced to a single value for which truthfulness is evaluated; second, how program flow changes based on the
condition
being True or False. The animations also show a new way to use the print
function
which we'll revisit later. Also noteworthy is the use of a new
operator
in the if statement: <. Just like in math, this is the "less than" operator. The table below shows all operators from this category:
== a == b a equals b
!= a != b inequality
< a < b a is less than b
<= a <= b a is less than or equal to b
> a > b a is more than b
>= a >= b a is more than or equal to b

In Search of True

Learning goals: Meaning of
comparison operators
.
Introduction
Assume the following statement where the operator has been replaced with X:
5 X 4
Answer Specification:
There are three comparison operators that, if used in place of X, will make the statement resolve as True. Write these operators on separate lines in the answer box.
Write the operators (nothing else), each on the their own line.
Warning: You have not logged in. You cannot answer.
Noteworthy properties:
In [1]: 1 == 1.0
Out[1]: True
In [2]: 1 == "1"
Out[2]: False
Whereas integers and
floating point numbers
can be equal to each other,
strings
can never be equal to either of them. This is important to remember because comparing user
inputs
in
conditional statements
can produce confusing False results if they haven't been converted to numbers. And, with inequality, it becomes the other way around:
In [1]: 1 != 1.0
Out[1]: False
In [2]: 1 != "1"
Out[2]: True
Comparisons between different types is not allowed with other
operators
:
In [1]: "doggos" < 3
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-7396907f20c6> in <module>()
----> 1 "doggos" < 3

TypeError: unorderable types: str() < int()
What can be confusing however is that you can compare strings in this way:
In [1]: "donkey" > "walrus"
Out[1]: False
In [2]: "monkey" > "mongoose"
Out[2]: True
The "size" of strings in this case is based on comparing them via alphabetical order. One common error scenario that can result from this: you prompt the user for two numbers and compare them, but forget to
convert
them into numbers:
In [1]: "31" > "4"
Out[1]: False
╯°□°)╯︵ ┻━┻

Checksum

One rather central aspect in Blackjack is checking if the sum of a hand exceeds 21. If we wanted to make a Blackjack program, there's a very high probability that we'd need a conditional statement for this at some point. Of course we're gonna leave it to you to write this statement.
Learning goals: How to write a
conditional statement
that compares numbers.
Introduction:
We're looking for a conditional statement that fits into this function:
def check_bust(hand_total):
    # conditional statement goes here
        return True
    else:
        return False
In other words the condition must be met if the hand_total variable exceeds 21.
Answer Specification:
When you have come up with a conditional statement that fills this purpose, pop into the answer box without indentation. Don't use needless parentheses either.
Resources:
If you want, you can also use the following skeleton of a program to test your function
blackjack_the_very_beginning.py
def check_bust(hand_total):
    # conditional statement goes here
        return True
    else:
        return False

total = int(input("Enter hand total: "))
if check_bust(total):
    print("You lost")
else:
    print("You didn't lose, at least not yet...")
The answer is the if statement, nothing else.
Warning: You have not logged in. You cannot answer.

Trident

A single
conditional statement
by itself is not particularly powerful. Luckily
conditional structures
can have multiple
branches
. If we take a look at our program structure diagram we notice that on the outer level we need a structure that has four distinct choices. In order to implement these choices we also need to decide how the user can indicate their choice. At simplest the user can be prompted to type either "length", "volume", "mass" or "temperature" which at least should be very straightforward. Let's start with this solution.
A good way to create a menu structure such as this is to use
functions
. Each part of the program gets its own function so that the main menu structure only
calls
these functions. This way the menu code itself is very clear and compact. Likewise each part of the program is now in its own function which makes them easier to implement and maintain, compared to if they were part of the
main program
where we place the conditional structure. Most importantly the conditional structure itself is easier to follow when there aren't too many lines of code inside each branch. Let's start drafting our program by defining a function for each of its main features, following the diagram:
def length():

def mass():

def volume():

def temperature():
This time our
functions
don't have any
parameters
. This is quite common in menu-like structures because there isn't anything relevant to pass on yet. This code isn't free of problems though. If you try to run it, Python reports an IndentationError. Whenever there's a colon that signifies a code
block
, it must be followed with at least one
indented
line. Still, it's occasionally good to be able to write function definitions without writing any of their content. Luckily Python has a useful feature that we can use: a command that does absolutely nothing, pass. It's often used as a temporary replacement for function contents so that the code can be run even if all functions aren't ready yet.
def length():
    pass

def mass():
    pass

def volume():
    pass

def temperature():
    pass
You can add new
branches
to
conditional structures
with the elif statement (abbreviation for "else if"). These statements must be placed on the same
indentation
level as the
if statement
that started the structure and as individuals they work just like it. However, only one branch in a single conditional structure can be selected. This means that the
code block
inside a particular branch can only be reached if none of the preceding (i.e. above it) conditional statements has been fulfilled. Turned around this means that as soon as one
condition
in the structure is fulfilled, the rest are not even assessed.
number = int(input("Give an integer: "))
if number < 10:
    print("Number is smaller than 10")
elif 10 <= number < 100:
    print("Number is smaller than 100")
elif 100 <= number < 1000:
    print("Number is smaller than 1000")
At a glance this looks logical. However, each elif in the code also contains the precedent that none of the conditions before it have been fulfilled. This means that the first comparison in both elif lines is in fact not needed (and therefore doesn't do anything). Basically:
This follows from the fact that we simply would not be evaluating the elif statements at all if the number had been smaller than 10, and we would not be evaluating the last one if the number had been smaller than 100. Using this information we can rewrite the structure:
number = int(input("Give an integer: "))
if number < 10:
    print("Number is smaller than 10")
elif 10 <= number < 100:
    print("Number is smaller than 100")
elif 100 <= number < 1000:
    print("Number is smaller than 1000")

The Burden of Proof

Learning goals: We'll see that only one
branch
is selected from a
conditional structure
.
Introduction:
Download the code from the resource link and run it twice. Input 8 on the first run and 108 on the second run.
Answer Specification:
For each run, copy the program's printed statements (i.e. without the
input
prompts) and paste them to the answer box.
Resources:
if_example.py
number = int(input("Give an integer: "))
if number < 10:
    print("The number is smaller than 10")
elif number < 100:
    print("The number is smaller than 100")
elif number < 1000:
    print("The number is smaller than 1000")
Copy the outputs (omit the input lines) to the answer field below.
Warning: You have not logged in. You cannot answer.
Now that we know what a
conditional structure
with multiple
branches
looks like using
elif statements
, we can draft the main menu code:
choice = input("Make your choice: ")
if choice == "length":
    length()
elif choice == "mass":
    mass()
elif choice == "volume":
    volume()
elif choice == "temperature":
    temperature()
The structure of the menu is now very easy to understand. The conditional structure guides the program execution into
functions
that correspond to each choice available to the user. Because the functions have been defined (despite not doing anything) this program can already be ran. This allows us to implement the program in small parts but still be able to check it for errors frequently. The functions themselves could also contain something like this:
def length():
    print("Length was selected")
If we now run the program, we get this print as proof that the program did indeed proceed to the correct function when "length" was selected. This is a good way to
debug
errors from conditionals statements that have complex, error prone
conditions
.
But why do we need elif specifically? Isn't it enough to have multiple if statements? The important difference is that an if statement starts a new conditional structure whereas elif continues a structure. Only one
branch
is executed from each conditional structure and conditions are only checked until one of them is true. So when the user selects "length" the other conditions aren't even checked. But if we had implemented this with only if statements all conditions would always be checked because we would have four separate single branch structures instead of one four branch structure. In this particular example there is no difference because there is no overlap between the conditions (a string cannot be both "length" and "mass" at the same time). Conditions that do have overlap demonstrate the difference a bit better:

Orderly Architect

The order of branches in a conditional structure matters. Each statement that is not fulfilled also produces information that can be used in later statements. For instance, if the first statement checks whether an animal is a donkey the remaining statements can safely assume the animal was not a donkey - if it had been a donkey, the first branch would have been selected and no one would have cared about the other branches. In this exercise we'll let you make use of this information.
Learning goals: Writing a
conditional structure
with multiple
branches
. Ordering of
conditional statements
inside a structure.
Goal: A program that makes a statement about a number's size.
Before You Begin:
Because writing and testing conditions is much more fruitful when you have something to check, you can start your code file with this prompt:
number = int(input("Input integer: "))
Main Program:
Your task now is to use the things you've learned so far to produce a condtional structure that evaluates a number using the following statements:
  • The number is bigger than 10
  • The number is bigger than 100
  • The number is bigger than 1000
Your code is allowed to only print one of these, and it always has to be the biggest possible (i.e. for 256 it should print the middle one). The code also cannot contain unnecessery comparisons - only one comparison is allowed for each statement. Pay attention to the order of
conditions
in the code and use it to your advantage.
Warning: You have not logged in. You cannot answer.

User Experience is Unconditional

Now we have some code that implements a main menu for our program using a
conditional structure
. However, its usability is a bit trash. For starters the user has no idea what options they have. This is easy enough to fix by printing some instructions before
input
prompt. Let's do this right away:
def length():
    pass

def mass():
    pass

def volume():
    pass

def temperature():
    pass

print("This program converts US customary units to SI units")
print("Available features:")
print("length")
print("mass")
print("volume")
print("temperature")
print()
choice = input("Make your choice: ")
if choice == "length":
    length()
elif choice == "mass":
    mass()
elif choice == "volume":
    volume()
elif choice == "temperature":
    temperature()
The last print
call
that has no
arguments
produces one empty line. Empty lines make the output a bit more readable. The same applies to code.
What would happen if the user - through either mischief or accident - inputs something that is not covered by the
conditions
in our
conditional structure
? At the moment the program just kicks the user back into the
terminal
without explanation. At least the program should say "The selected feature is not available". This is something that's best done with the third component of conditional structures, else. It covers all the situations that didn't fulfil the conditions for any of the other
branches
, and it must always be last. It is not mandatory to have one - obviously, given that our code ran previously just fine without one. Let's put it to use:
if choice == "length":
    length()
elif choice == "mass":
    mass()
elif choice == "volume":
    volume()
elif choice == "temperature":
    temperature()
else:
    print("The selected feature is not available")
The else statement is the simplest part of the structure because it doesn't have a
condition
. It's simply the dumping ground where all the misfit cases fall into.
Now the program is much friendlier. It gives some instructions and can even say something if things go wrong. Let's try it!
Image source 4

Size Does Matter

Learning goals: You'll see that the size (of letters) does matter.
Introduction:
Download the program from the resources section. Run the program and input "Length" when prompted.
Answer Specification:
Copy the program's response to the answer box.
Resources:
converter.py
def length():
    print("Length was selected")

def mass():
    print("Mass was selected")

def volume():
    print("Volume was selected")

def temperature():
    print("Temperature was selected")

print("This program converts US customary units to SI units")
print("Available features:")
print("length")
print("mass")
print("volume")
print("temperature")
print()
choice = input("Make your choice: ")
if choice == "length":
    length()
elif choice == "mass":
    mass()
elif choice == "volume":
    volume()
elif choice == "temperature":
    temperature()
else:
    print("The selected feature is not available")
Copy the program's answer to this box,
Warning: You have not logged in. You cannot answer.

Methodical Characters

We ran into a problem: if the user gives a command that's technically correct but starts with a capital letter, the command is not recognized. We could just blame the user but that feels a bit unfair. Especially because we probably could accept typing variations pretty easily. The crux of the issue is that lower and upper case letters are not the same symbols:
In [1]: "A" == "a"
Out[1]: False
The most straightforward idea would be to add a condition that recognizes the "Length"
string
. But what if the user has caps lock on and they
input
"LENGTH" or "lENGTH"? In the long term it's probably better for our sanity to do the comparison in a way that it's not case sensitive. A good way to go about this is to convert all letters in the user's input to lower case. This can be done with a
method
.
Learning goals: This section teaches you what methods are and what you can do with string methods.

Hey There, I'm a Method

Methods belong under the category of
functions
. The difference to functions as we've known them so far is that methods are attached to
objects
- they belong to the object's attributes. In Python, object can refer to any
value
. The word object is used here to signify something that has
attributes
because it sounds more logical than saying that values have attributes. That sounds fancy, but what does it actually mean? Example time:
number = round(number)
When functions are called we usually define what object they should handle - we give it as an
argument
. In this case the round function handles an object that's in the number
variable
(i.e. the object is the variable's value). When a method is called it instead handles the object it is attached to. Shown below is a
Python console
example of using the strip method. You don't need to fully understand what's going on, but you can try it already!
In [1]: creature = "   donkey    "
In [2]: creature.strip()
Out[2]: 'donkey'
Each
object's
set of
methods
depends on its
type
. For instance, all
strings
have the same methods. The full list can be found from Python's documentation (surprise?). If you're working in the console you can also see the list of an object's
attributes
(including its methods) with the dir
function
. You can do this by using any string as the dir function
argument
, e.g empty string:
In [1]: dir("")
Out[1]: 
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getnewargs__',
 '__gt__',
 '__hash__',
 '__init__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mod__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rmod__',
 '__rmul__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'capitalize',
 'casefold',
 'center',
 'count',
 'encode',
 'endswith',
 'expandtabs',
 'find',
 'format',
 'format_map',
 'index',
 'isalnum',
 'isalpha',
 'isdecimal',
 'isdigit',
 'isidentifier',
 'islower',
 'isnumeric',
 'isprintable',
 'isspace',
 'istitle',
 'isupper',
 'join',
 'ljust',
 'lower',
 'lstrip',
 'maketrans',
 'partition',
 'replace',
 'rfind',
 'rindex',
 'rjust',
 'rpartition',
 'rsplit',
 'rstrip',
 'split',
 'splitlines',
 'startswith',
 'strip',
 'swapcase',
 'title',
 'translate',
 'upper',
 'zfill']
It returns a list of attributes. The ones in the beginning that are prefixed with underscores are intended only for the object's internal use and generally should not be touched. Just ignore them. The rest are all methods (in this case), and what we are interested in. Like functions they generally have more or less descriptive names. Let's take another method example that also completely coincidentally solves our current problem:
In [1]: word = "DoNkEy"
In [2]: word.lower()
Out[2]: 'donkey'
We could technically shorten this example to "DoNkEy".lower(), just to show you that you can attach
method calls
to
literals
as well. The period separates the
object
from its
method
. In other words the first part of the method call defines which object's method is being called, and the part after the period defines which method is called.
One notable thing about this particular method call is that the parentheses are empty. This follows directly from the fact that the method operates on the object it belongs to. The information that would be inside the parentheses in a
function call
is now on the left side of the period instead. This does not mean there aren't methods that also have
arguments
. After all, we do have functions with more than one argument as well.
As our third example let's look at the count
method
that can be used for counting how many times a shorter
string
occurs inside another, longer string. Once again you can check what the method does from the documentation, or you can check it in the
console
:
In [1]: help("".count)
Help on built-in function count:

count(...) method of builtins.str instance
    S.count(sub[, start[, end]]) -> int

    Return the number of non-overlapping occurrences of substring sub in
    string S[start:end].  Optional arguments start and end are
    interpreted as in slice notation.
The line that shows how to use the method has an S before the period. This is where you put the longer string where you want to count occurrences of the shorter string from. Inside the parentheses you can see the method's three
arguments
first of which, sub, is mandatory while the other two, start and end, are optional (the square braces indicate this). Out of these, sub is the substring that we want to count. The optionals can be used to limit the search to only part of the S string.
This method can be used for counting things like how many
comparison operators
are in a code file, or whether there's the correct number of elif statements in
conditional structures
. This kind of code checking is called static checking where code is read as text instead of running it. That's just one use for scrutinizing
strings
though. Reading and processing text on a computer is a major field in computer science, and you can start it with simple tricks like:
text = input("Write a poem: ")
donkeys = text.count("donkey")
print("Your text contained", donkeys, "donkey(s))")

Meta-if

This exercise puts you in the shoes of people who write these checkers. The problem at hand is: how to find out whether there's a colon at the end of a student's conditional statement.
Learning goals: Using
methods
in
conditional statements
. Searching methods from the documentation, because it's important.
Introduction:
Once again figuring out the answer is easier when you have something to try it on. Let's start by
assigning
a sample
string
to a
variable
that you can examine in your conditional statement.
In [1]: line = "if animal == \"donkey\":"
Answer Specification:
The answer must be a conditional statement that examines whether a given line ends with a colon. This can be achieved with a certain string
method
(you can find a link to a list of string methods by putting the mouse cursor over the method term). In other words the condition should be True for the sample line. Use the given variable in your answer and don't forget to end with a colon yourself =p

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

Method Chaining

String methods
can also be chained. This follows from the fact that most string methods
return
a derived copy of the
string
. When the line is executed, we can think of the method's return value replacing the
method call
- just like we did with functions. There's also an important fact here: a string method never modifies the original string. The reason for this is that strings are an
immutable
type
. The meaning of this will be clarified a bit later when we encounter the first type that is mutable. For now we have this animation to illustrate how strings methods,
variables
and their values interact with each other.
The same animation also shows that after the dust settles, there is a
string
in place of the
method call
. One method that is commonly used in chaining is strip. Let's consider a scenario where we want to add leading zeros to a number prompted from the user so that the number will always have 4 digits. The method that does this is zfill. It takes the desired minimum length as its
argument
. The code would look like this:
number = input("Input number between 1 and 9999: ")
number = number.zfill(4)
print(number)
Normally this seems to work just fine:
Input number between 1 and 9999: 42
0042
However, what if the user accidentally puts some spaces before or after the number (or both, like in this example - you can highlight the text to see the trailing space)
Input number between 1 and 9999:  42 
 42 
This is exactly the kind of a scenario where the strip method shines. Its default behavior is to remove all empty characters from the beginning and end of a
string
. The other empty characters besides spaces are newlines and tabs. It can also be given another set of characters to remove instead as an optional argument but stripping blanks is by far the most common use case. The method also has two relatives, lstrip and rstrip, that do the same thing but only from the beginning (lstrip, left) or end (rstrip, right). This method should be called before the zfill method, resulting in code like this:
number = input("Input number between 1 and 9999: ")
number = number.strip().zfill(4)
print(number)
The execution of this line is explained in the following animation using " 42 " as a
value
for the number
variable
.

Advanced Meta-if

Let's continue our expedition into the life of TAs. We all know how much complaining there would be if checkers rejected a conditional statement that does have a colon at the end but also happens to have an extra space or newline at the end... this should probably be handled somehow. It ain't easy to be a TA.
Learning goals: Using more than one
method call
in a
conditional statement
. Even more rummaging around documentation to find
methods
.
Introduction:
Let's change the sample line to include some extra spaces and even a newline at the end.
In [1]: line = "if animal == \"donkey\":   \n "
Answer Specification:
Once again the answer is a conditional statement that checks whether there's a colon at the end. There is, however, a new twist. Your answer must ignore any blank characters at the end of a string, including spaces, tabs and newlines. In other words it must accept the new sample line.
Write the code line below.
Warning: You have not logged in. You cannot answer.
Now we can finally get back to the issue that sent us off on this wild
method
chase. The problem was that "length" and "Length" are entirely different things according to Python. We did already find a method to solve this issue: lower, which converts all letters of a
string
to lower case. We also found a neat little method that strips all accidental blanks from an input. Luckily method calls can also be chained after any old
function calls
as long as they return strings. Coincidentally input just happens to be that kind of a function. This allows us to use the following solution:
choice = input("Make your choice: ").strip().lower()
Because we don't need the raw input elsewhere in the program, chaining calls like this is the best way to process it. This way we don't need to bother with the processing in multiple places and we also don't need to have a separate line for it. The
main program
as a whole becomes:
print("This program converts US customary units to SI units")
print("Available features:")
print("length")
print("mass")
print("volume")
print("temperature")
print()
choice = input("Make your choice: ").strip().lower()
if choice == "length":
    length()
elif choice == "mass":
    mass()
elif choice == "volume":
    volume()
elif choice == "temperature":
    temperature()
else:
    print("The selected feature is not available")

Operation Logic

If we're being completely real here, typing entire words in order to navigate a menu is pretty rude. In the modern world people mostly interact with menus using a mouse or touch screen but even back when we were programming next to bonfires in caves we had means to make menus a bit more painless. There's typically two ways to go about this. We can either enumerate the choices so that the user inputs a number to make a choice; or we can choose a letter to correspond with each choice (usually its initial letter if possible). Enumeration would result in an
interface
that looks like this:
Available features:
1 - Length
2 - Mass
3 - Volume
4 - temperature

Make your choice (1-4): 
Whereas using single letters would give us something like:
Available features:
(L)ength
(M)ass
(V)olume
(T)emperature

Make your choice: 
The letters in parentheses indicate which character to input to choose a feature. This time we're going to go with the latter approach. This causes changes to how our instructions are printed and of course to the
conditional structure
that handles the choice making.
We're actually going to be so understanding that the program doesn't only accept these single letter inputs but it will also accept full words.
Boolean operators
allow us to do this. They can be used to combine and negate existing
conditions
. There's whole three of them: and, not, and or. They are just like any other
operators
(e.g. + or >=) but just happen to be words in Python. A lot of languages actually use symbols for these operators, mainly: &&, ! ,and ||, but the words in Python are a bit more descriptive. They are primarily used in
conditional statements
when multiple conditions need to be combined, or one needs to be reversed.
Image source 5
Let's start with the not operator which performs logical negation. One of the most common use cases for this is to check whether the user's
input
is entirely empty. An empty
string
means a string that has no characters i.e. its length is zero. "" and '' are the only empty strings. For instance " " is not empty because it contains a single space, and its length is one. You could test for an empty string like this:
if choice == "":
but the preferred way is:
if not choice:
This line works the way it does because the
truthfulness
of an empty string is False. Negation with the not operator reverses this, return True if the condition itself is False, and False if the condition is True. A notable characteristic of the
operator
is that it has only one
operand
and it's always on its right side. For all intents and purposes it functions like a minus sign in front of a number.
The other two
boolean operators
(and, or) are more commonly used because they can combine two
conditions
. The result of the combination depends on the operator: and evaluates to True if and only if both operands are True; or evaluates to True if at least one of the its operands is True. For our current need, or does the job. We can test what it does outside conditional statements in the console:
In [1]: choice = input("Make your choice: ").strip().lower()
Make your choice: L
In [2]: choice == "l" or choice == "length"
Out[2]: True
If we had used the and operator in the above example we would have created a condition that can never be True. The reason is simple: a
string
cannot have two different values ("l" and "length") at the same time. The and operator is more often used in cases where two variables are checked at the same time, or one variable is checked in two different ways. One such use case could be checking if a point is the origin:
if x == 0 and y == 0:
Finally a word of warning about a common error:
if choice == "l" or "length":
When you read this aloud it might seem to make sense. However, if you read it like Python does, it turns out the operands of the or operator are actually choice == "l" and "length". As happened in the example when the user chose "m", the first operand is obviously False because "m" is not the same as "l". However, the second
operand
- just the
string
"length" by itself - is always True because it's not an empty string. The equality
comparison operator
== only exists on the left side of the or operator. Once we reach the right side of the operator, the equality comparison no longer really exists. In other words this condition is always True regardless of what the user
inputs
. It may feel stupid to write the whole comparison twice on the same line but we don't have a shorter way to express this - yet.

The Snake's Tongue

''Let's take another trip to the wonderful world of text analysis. This time we're looking for texts that contain the words "python" and "programming", both at least once. This could be used for finding writings about Python programming specifically without including general programming articles in the results - not to mention ones about snakes.
Learning goals: Using
boolean operators
in
conditional statements
.
Introduction:
Once again we'll give you a sample
string
to examine:
In [4]: text = """ 
   ...: thing is, programming is fun until javacsript happens -  
   ...: after that you just kinda fall into endless darkness 
   ...: """
Answer Specification:
Once again we're looking for a conditional statement, keyword, colon, and everything. The condition should be fulfilled if both "python" and "programming" are present in the string at least once. You can use the count
method
for finding occurrences. Feel free to assume the entire text has been converted to lower case - your conditional statement doesn't need to fuss about case. Use the text variable in your answer.
The answer is just the if statement.
Warning: You have not logged in. You cannot answer.
As the result of this section, the
main program
has now taken this shape:
print("This program converts US customary units to SI units")
print("Available features:")
print("(L)ength")
print("(M)ass")
print("(V)olume")
print("(T)emperature")
print()
choice = input("Make your choice: ").strip().lower()
if choice == "l" or choice == "length":
    length()
elif choice == "m" or choice == "mass":
    mass()
elif choice == "v" or choice == "volume":
    volume()
elif choice == "t" or choice == "temperature":
    temperature()
else:
    print("The selected feature is not available")

Python's Style Academy

Let's go back to the program structure diagram:
Program structure. Implemented part circled with red. Next task circled with blue
We have a stub code for the the part circled with blue in the figure already. This
stub function
was used for showing that the menu implementation in the
main program
worked as intended.
def length():
    print("Length was selected")
Our next goal is to turn this stub into a strong independent function. This function needs to prompt the user for two things: measurement unit and value. Way earlier we decided that the available units would be inch, foot, yard and mile. In addition to prompting these two things the function should use them to calculate the corresponding value in SI units. Inches and feet can be converted to centimeters, yards to meters and miles to kilometers. If we make decisions about the target unit like this without asking, it would also be polite to include it in the result. A use case could look like this:
Input unit: inch
Input value: 12.4
12.40" is 31.50 cm
Following the solution model we learned before, this could be implemented with a
conditional structure
that has five
branches
(4 for
conditional
branches and 1 else for invalid unit choice), each containing their own calculation and output. This time there is little point in making separate
functions
for each choice and instead their implementation should just be included inside the structure. Let's once again start with a stubbed version that doesn't have any additional fluff like instructions. The structure is already familiar from the
main program
. Each conversion comes down to value * factor, and the factors can be found from wikipedia
def length():
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "inch":
        print(value * 2.54)
    elif unit == "foot":
        print(value * 39.48)
    elif unit == "yard":
        print(value * 0.9144)
    elif unit == "mile":
        print(value * 1.609344)
    else:
        print("The selected unit is not supported")
With the functionality in place we get to this section's beef: formatting the results.
Learning goals: This section teaches you that some characters in strings can be problematic. Another important take away is how to produce beautiful output using the format method. Rounding gets revisited. After this section you'll be able to print all kinds of strings.

Escapism

We can do unit selection based on its abbreviation or symbol. In this case, in/", ft/', yd and mi. Let's start by plopping these in to the
conditional statements
we wrote just now. We'll use the or
operator
for inches and feet so that both ways to choose them can be implemented.
def length():
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "in" or unit == """:
        print(value * 2.54)
    elif unit == "ft" or unit == "'":
        print(value * 39.48)
    elif unit == "yd":
        print(value * 0.9144)
    elif unit == "mi":
        print(value * 1.609344)
    else:
        print("The selected unit is not supported")
You should immediately notice that the syntax highlighting in this code looks a bit off. If one " character starts a string and a second one ends it, how should """ be interpreted? Trying to run this code gives an
error message
  File "/media/sf_virtualshare/OA/code/M2/converter_1.py", line 41
    print("The selected feature is not available")
                                                  
^
SyntaxError: EOF while scanning triple-quoted string literal
Triple-quoted string literal means a
string
that's been delimited with three quotation characters instead of single ones. So, a fact we've kept from you so far: """ also starts a string. Because there's no matching end delimiter for it in the file, Python encounters the end of the file before the end of the string, and ultimately throws a SyntaxError because of it. """ is actually a bit different from single quotes - strings delimited by them can go on for multiple lines:
poem = """such string
many line"
wow"""
Well, that's cool? Doesn't solve the problem though. In general having the " character inside a string that's delimited with " characters is a bit problematic. We could sidestep the issue by delimiting with ' instead. This in turn would make ' characters inside the string problematic. Plus we would still run into problems with strings that contain - heavens forbid - both ' and ". Then what? Well, we're going to
escape
. That's what.
Image source 6
Let's not get off our computers and skedaddle to the woods though. We're just going to use something called an escape character. In Python this character is backward slash, \. Using this character inside a string in front of another character changes the way the character is interpreted. For instance, an escaped ", i.e. \", is interpreted as the quote character instead of string delimiter. In code it looks like this:
In [1]: double_quote = "\""
In [2]: print(double_quote)
"
The character (or sometimes characters) after \ is interpreted differently. In other words it is escaped. Let's add this tech to our code:
def length():
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "in" or unit == "\"":
        print(value * 2.54)
    elif unit == "ft" or unit == "'":
        print(value * 39.48)
    elif unit == "yd":
        print(value * 0.9144)
    elif unit == "mi":
        print(value * 1.609344)
    else:
        print("The selected unit is not supported")
Now we have a program that can already handle length conversions. It's still missing some of the prettifications that we planned to have though.

Beauty School

Instructional prints are easy enough to add to the beginning of the
function
since they are in no way different from what we did in the
main program
. For results the plan was to make them print like this:
12.40" is 31.50 cm
In an earlier example we saw a print
function call
that had more than one
argument
and it looked like this:
print("Added", name, "x", count)
It produced the following output when the variables had the values "donkey" and 1 respectively:
Added donkey x 1
The print function can accept an indefinite number of arguments, all of which will be printed on the same line, separated by spaces. As can be seen from the example each argument can be different: this one has both
literal values
and
variables
- in fact the variables even have different types since one is a
string
and one is an integer. It's therefore perfectly to valid to mix different
types
in the arguments too. We can use this in our first attempt to print variable values inside an output line:
print(value, "\"", "is", value * 2.54, "cm") 
We can try it in the
Python console
:
In [1]: value = 12.4
In [2]: print(value, "\"", "is", value * 2.54, "cm")
12.4 " is 31.496000000000002 cm
Close, but no bananas. The " character is separated from the value, the second decimal of 12.4 is missing (we wanted to show the 0) and the result hasn't been rounded. We can try to solve the most pressing issue - the lack of rounding - by dropping a round
function call
inside the print call.
In [1]: value = 12.4
In [2]: print(value, "\"", "is", round(value * 2.54, 2), "cm")
12.4 " is 31.5 cm
Now the result is missing the desired second decimal as well. On top of that the code line starts to look really messy and it's hard to figure out what the output would look like. In general it's much preferable to use formatting tools for constructing any kinds of more complex
strings
. In Python this purpose is served by the
format method
, one of the string
methods
. It's a rather multifaceted method with a wide variety of uses, and using it requires some fresh new knowledge. The string whose format method is called serves as sort of a template that defines spots and potential formatting instructions for
values
to be inserted in. A lot like elementary school assignments where you had to fill in the blanks:
_____" is  _____ cm
Well, we're not using underscores to mark the spots, but we do have another way to mark them. A simplest possible template for what we're trying to do is:
"{}\" is {} cm"
In this code the curly braces define spots where something else will be plopped into. The "what" that gets plopped in is given in the format
method call
as
arguments
. Like print, format also can take any number of arguments that can be all kinds of values. In its simplest form, the first argument will replace the first pair of curly braces, the second argument will replace the second pair and so on. Because it's a method call, it's placed at the end of the template string itself, with a period between them. Let's replace the monster of a print with one that uses the format method:
In [1]: value = 12.4
In [2]: print("{}\" is {} cm".format(value, round(value * 2.54, 2))) 
12.4" is 31.5 cm
The code itself doesn't look much better but at least the line has a bit better structure: the shape of the output is easily readable from the beginning and all the values that will be placed into it are on the right. We also managed to attach the " firmly to the number, something the print call by itself didn't manage.

What Do We Have Here?

In this exercise we're working on a memory game. Well, sort of. We're implementing the one line that tells a player what's in the tile they selected. The tile selection has been done with x and y coordinates and its contents are described by a word. Now, what wonder we might have chosen for this...?
Learning goals: Formatting
strings
with the
format method
and simple
placholders
.
Introduction:
Let's start by a few
variable
assignments
so you can use them in your formatting line:
In [1]: x = 5
In [2]: y = 6
In [3]: thing = "donkey"
Answer Specification:
Write a line that prints messages in the format of "Tile (5, 6) contains donkey". You need to use the format method in your answer. Write a template string with three placeholders, and the format
method call
that places the three variables into the placeholders. The string should also be printed. All of this in one line please.
Write the entire code line as your answer
Warning: You have not logged in. You cannot answer.

Curly Keys

So far we've learned that curly braces define
placeholders
for values inside
strings
. There's more to their power however. For one, they can be more accurate about what will replace them. Empty braces like the ones we used will get their values in corresponding order from the
format
method call
arguments
. One potential issue here is that as the number of placeholders and arguments grows the code becomes harder and harder to read. In addition they are very error prone: whenever the template string is modified, the method call arguments also have to be updated in case placeholder order or number has changed.
Often a better way is to give names to each placeholder and name the arguments accordingly.
"{us_value}\" is {si_value} cm".format(us_value=value, si_value=round(value * 2.54, 2))
There's a name for giving arguments like this:
keyword argument
. Normally the order of
arguments
in a
function call
defines which
parameter
receives which argument. Keywords can be used to directly control which parameter receives which argument instead. For example, given that round function's parameters are named number and ndigits it would be perfectly valid to call it like this (names can be found from documentation).
In [1]: round(ndigits=1, number=4.451)
Out[1]: 4.5
The format method is just a bit more special because it has no mandatory arguments, but instead has theoretically infinite
optional arguments
. It can receive arbitrary keyword arguments as we saw earlier. Python developers most certainly haven't defined
parameters
like us_value or si_value for the
format
method.
Oh and what heresy is this?! We didn't put spaces around the
assignment
operator (=)! That was actually intended - the style guide specifically makes an exception for
keyword
assignment and
default value
definition. This is the one strange exception we have so it shouldn't be too hard to remember. That's far less exceptions than in the English grammar you know.
The advantage of using
keyword arguments
with the format method is that giving names to
placeholders
and values that will go into them makes the connection way more apparent. This is also much less error prone when changes are made. But wait there's more! It also allows using the same placeholder multiple times without repeating the argument in the format method call.
Let's look at another example from a hypothetical program that saves music files on the computer putting them into folders based on their encoding (e.g. mp3, ogg), then artist and finally album. The resulting filename itself will be in the format "Wolves in the Throne Room - 01 - Queen of the Borrrowed Light.ogg" i.e. artist name, track number, track title and finally file extension. We'll define all these as variables in the console:
In [1]: extension = "ogg"
In [2]: artist = "Alcest"
In [3]: title = "Eclosion"
In [4]: track_no = "02"
In [5]: album = "Kodama"
Formatting the file path "traditionally":
In [6]: "{}/{}/{}/{} - {} - {}.{}".format(extension, artist, album, artist, track_no, title, extension)
Out[6]: 'ogg/Alcest/Kodama/Alcest - 02 - Eclosion.ogg'
The same with keywords. This example also shows how to properly split a long method call into multiple lines for increased readability.
In [7]: "{extension}/{artist}/{album}/{artist} - {track_no} - {title}.{extension}".format(
   ...:     extension=extension,
   ...:     artist=artist,
   ...:     album=album,
   ...:     track_no=track_no,
   ...:     title=title
   ...: )
Out[7]: 'ogg/Alcest/Kodama/Alcest - 02 - Eclosion.ogg'
The latter is certainly longer but the template for the name is way more descriptive. In the first method it's not enough to look at the template when reading the code, you also need to look at the
arguments
if you want to understand what the result will look like. The latter also avoids giving the same argument multiple times. In this particular example the
parameters
and arguments happen to have the same names. This is not a problem. As we should remember from last material, parameters exist in a different
scope
from the variables that serve as arguments. But please note that they could have different names as well!
Let's update our program to use
keyword arguments
:
def length():
    print("Select unit of length from the options below using the abbreviations")
    print("Inch (in or \")")
    print("Foot (ft or ')")
    print("Yard (yd)")
    print("Mile (mi)")
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "in" or unit == "\"":
        print("{us_value}\" is {si_value} cm".format(us_value=value, si_value=round(value * 2.54, 2)))
    elif unit == "ft" or unit == "'":
        print("{us_value}' is {si_value} cm".format(us_value=value, si_value=round(value * 39.48 2)))
    elif unit == "yd":
        print("{us_value} yd is {si_value} m".format(us_value=value, si_value=round(value * 0.9144, 2)))
    elif unit == "mi":
        print("{us_value} mi is {si_value} km".format(us_value=value, si_value=round(value * 1.609344)))
    else:
        print("The selected unit is not supported")

What Do We Have Here This Time?

It's the same example but we want to write the formatting line a bit differently. The way presented here is generally easier to read and a bit more flexible. The player in our example is less flexible, and opens the same tile again...
Learning goals: More
string
formatting with the
format
method. This time using
keyword arguments
.
Introduction:
Let's start with a familiar set of
variables
:
In [1]: x = 5
In [2]: y = 6
In [3]: thing = "donkey"
Answer Specification:
The end result should be the same as last time. This time you must use named
placeholders
and keyword arguments in the
method call
. Due to lack of imagination, we're going to use the same names for the placeholders as we did for the variables. This doesn't cause any problems since the names are in different
scopes
but may look a bit weird. Like last time, there should be no
literal values
in your answer. Here's the expected result in case you've forgotten: "Tile (5, 6) contains donkey".
Just for the sake of our own sanity we've defined the answer in such a way that the keyword arguments must be given in the same order as the placeholders are. In practice this doesn't matter, but if you saw how this thing is checked you'd agree too.
Write the line of code below.
Warning: You have not logged in. You cannot answer.

Curly Styling

The power of placeholders doesn't end with specifying what values will be placed where in a
string
. They can also define additional formatting for the values. This material has two example cases that will both have some uses on a basic level course. One of these is adding leading zeros to integers and the other is defining how many decimals to display for
floats
. Leading zeros are typically used for dates and times. A computer-readable timestamp usually looks like this: "2015-06-29 09:46:06". Adding the zeros is done with a placeholder that has additional formatting specification:
In [1]: "{hours:02}".format(hours=9)
Out[1]: '09'
The colon in the
placeholder
separates the formatting specification from the naming part. The zero following the colon indicates that we want to add leading zeros, whereas the 2 after that indicates that the result must be at least 2 characters long. In other words, zeros will be added if the value is shorter than 2 characters.
Defining decimal precision is even more commonly done. This can be achieved with a pretty similar syntax:
In [1]: "{length:.2f}".format(length=4.451)
Out[1]: '4.45'
This time the . character indicates that the number following it will be defining the desired decimal precision. The f at the end indicates that the value to be placed here must be treated as a float. If you don't have the f there this line can cause the following
exception
if the argument is an integer:
ValueError: Precision not allowed in integer format specifier
Precision cannot be defined for integers because they don't have a decimal part. Defining precision means adding trailing zeros if necessary:
In [1]: "{length:.2f}".format(length=4)
Out[1]: '4.00'
This also eliminates the need to use the round
function
because rounding is done by the formatting instead. This allows us to clean up our code lines a bit:
print("{us_value:.2f}\" is {si_value:.2f} cm".format(us_value=value, si_value=value * 2.54))
With this the function becomes:
def length():
    print("Select unit of length from the options below using the abbreviations")
    print("Inch (in or \")")
    print("Foot (ft or ')")
    print("Yard (yd)")
    print("Mile (mi)")
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "in" or unit == "\"":
        print("{us_value:.2f}\" is {si_value:.2f} cm".format(us_value=value, si_value=value * 2.54))
    elif unit == "ft" or unit == "'":
        print("{us_value:.2f}' is {si_value:.2f} cm".format(us_value=value, si_value=value * 39.48))
    elif unit == "yd":
        print("{us_value:.2f} yd is {si_value:.2f} m".format(us_value=value, si_value=value * 0.9144))
    elif unit == "mi":
        print("{us_value:.2f} mi is {si_value:.2f} km".format(us_value=value, si_value=value * 1.609344))
    else:
        print("The selected unit is not supported")
And this test run shows how pretty the results are:
This program converts US customary units to SI units
Available features:
(L)ength
(M)ass
(V)olume
(T)emperature

Make your choice: l
Select unit of length from the options below using the abbreviations
Inch (in or ")
Foot (ft or ')
Yard (yd)
Mile (mi)
Input source unit: mi
Input value to convert: 65
65.00 mi is 104.61 km
Using the
format method
for formatting has a wide variety of possibilities. This wealth of options can be admired at Python's documentation.

What Time is it?

The title of this task is starting to be relevant given how long we've been wading through this material. Luckily we can turn this into an exercise. This time we'll learn how to present times with leading zeros.
Learning goals: Formatting
strings
one more time. This time to learn how to add additional styling - like leading zeros - to
placeholders
.
Introduction
We'll create a time by splitting it into two
variables
:
In [1]: hours = 3
In [2]: minutes = 15
Answer Specification:
Once again we're looking for a line of code that prints a formatted line. Hours and minutes must always be printed with two numbers. This means they need leading zeros if they only have a single digit. The variables in the example would therefore print as "The time is 03:15". It's highly likely that you'll need some of the formatting things we just went over.
Type your answer below, with using the print function.
Warning: You have not logged in. You cannot answer.

Tying Strings Together

Here's the good news: of the remaining three
functions
we need to implement, two are pretty much identical to the length function. They just have different units and calculations. This means we can just write them out without further explanation. For mass we only have two units: ounce (oz) and pound (lb).
def mass():
    print("Select unit of mass from the options below using the abbreviations")
    print("Ounce (oz)")
    print("Pound (lb)")
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "oz":
        print("{us_value:.2f} oz is {si_value:.2f} g".format(us_value=value, si_value=value * 28.349523125))
    elif unit == "lb":
        print("{us_value:.2f} lb is {si_value:.2f} kg".format(us_value=value, si_value=value * 0.45359237))
    else:
        print("The selected unit is not supported")
And for volume:
def volume():
    print("Select unit of mass from the options below using the abbreviations")
    print("Cup (cp)")
    print("Pint (pt)")
    print("Quart (qt)")
    print("Gallon (gal)")
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "cp":
        print("{us_value:.2f} cp is {si_value:.2f} dl".format(us_value=value, si_value=value * 2.365882365))
    elif unit == "pt":
        print("{us_value:.2f} pt is {si_value:.2f} dl".format(us_value=value, si_value=value * 4.73176473))
    elif unit == "yd":
        print("{us_value:.2f} qt is {si_value:.2f} l".format(us_value=value, si_value=value * 0.946352946))
    elif unit == "mi":
        print("{us_value:.2f} gal is {si_value:.2f} l".format(us_value=value, si_value=value * 3.785411784))
    else:
        print("The selected unit is not supported")
For temperature we only have one unit to convert so we don't need to ask. This makes the function quite a bit shorter. The conversion from Fahrenheit to Celsius on the other hand is an artform in itself and cannot be done with a simple multiplication. For this reason we're calculating it separately to a variable instead of dropping the whole mess inside the format
method call
. The entire function looks like:
def temperature():
    print("Temperature conversion from Fahrenheit to Celsius.")
    fahrenheit = float(input("Input temperature: "))
    celcius = (5 / 9) * (fahrenheit - 32)
    print("{us_value:.2f} °F is {si_value:.2f} °C".format(us_value=fahrenheit, si_value=celcius))
We could have written the code inside each function to the
main program
as they are, in place of the
function calls
. There would be no difference in how the program works. This would just add more indentation levels to the
conditional structure
we have there. It sort of has the same amount of levels as is, we've just hidden that into the functions. If we got rid of all the functions, the main program would look like this:
print("This program converts US customary units to SI units")
print("Available features:")
print("(L)ength")
print("(M)ass")
print("(V)olume")
print("(T)emperature")
print()
choice = input("Make your choice: ").strip().lower()
if choice == "l" or choice == "length":
    print("Select unit of length from the options below using the abbreviations")
    print("Inch (in or \")")
    print("Foot (ft or ')")
    print("Yard (yd)")
    print("Mile (mi)")
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "in" or unit == "\"":
        print("{us_value:.2f}\" is {si_value:.2f} cm".format(us_value=value, si_value=value * 2.54))
    elif unit == "ft" or unit == "'":
        print("{us_value:.2f}' is {si_value:.2f} cm".format(us_value=value, si_value=value * 39.48))
    elif unit == "yd":
        print("{us_value:.2f} yd is {si_value:.2f} m".format(us_value=value, si_value=value * 0.9144))
    elif unit == "mi":
        print("{us_value:.2f} mi is {si_value:.2f} km".format(us_value=value, si_value=value * 1.609344))
    else:
        print("The selected unit is not supported")
elif choice == "m" or choice == "mass":
    print("Select unit of mass from the options below using the abbreviations")
    print("Ounce (oz)")
    print("Pound (lb)")
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "oz":
        print("{us_value:.2f} oz is {si_value:.2f} g".format(us_value=value, si_value=value * 28.349523125))
    elif unit == "lb":
        print("{us_value:.2f} lb is {si_value:.2f} kg".format(us_value=value, si_value=value * 0.45359237))
    else:
        print("The selected unit is not supported")
elif choice == "v" or choice == "volume":
    print("Select unit of mass from the options below using the abbreviations")
    print("Cup (cp)")
    print("Pint (pt)")
    print("Quart (qt)")
    print("Gallon (gal)")
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "cp":
        print("{us_value:.2f} cp is {si_value:.2f} dl".format(us_value=value, si_value=value * 2.365882365))
    elif unit == "pt":
        print("{us_value:.2f} pt is {si_value:.2f} dl".format(us_value=value, si_value=value * 4.73176473))
    elif unit == "yd":
        print("{us_value:.2f} qt is {si_value:.2f} l".format(us_value=value, si_value=value * 0.946352946))
    elif unit == "mi":
        print("{us_value:.2f} gal is {si_value:.2f} l".format(us_value=value, si_value=value * 3.785411784))
    else:
        print("The selected unit is not supported")
elif choice == "t" or choice == "temperature":
    print("Temperature conversion from Fahrenheit to Celsius.")
    fahrenheit = float(input("Input temperature: "))
    celcius = (5 / 9) * (fahrenheit - 32)
    print("{us_value:.2f} °F is {si_value:.2f} °C".format(us_value=fahrenheit, si_value=celcius))
else:
    print("The selected feature is not available")
This huge mess just makes it a lot harder to figure out how the program works. In particular the outer conditional structure becomes so long that the if that starts and the else that ends it don't fit on the same screen (or barely fit). If you compare this to the main program that uses function calls like we implemented it, it should be obvious how much clearer the entire thing is.
print("This program converts US customary units to SI units")
print("Available features:")
print("(L)ength")
print("(M)ass")
print("(V)olume")
print("(T)emperature")
print()
choice = input("Make your choice: ").strip().lower()
if choice == "l" or choice == "length":
    length()
elif choice == "m" or choice == "mass":
    mass()
elif choice == "v" or choice == "volume":
    volume()
elif choice == "t" or choice == "temperature":
    temperature()
else:
    print("The selected feature is not available")
The entire program can be download below.
converter.py

A Word on Dictionaries

If we look at the
conditional structures
of our unit converter we can discern a particular pattern: the structure is mostly used for choosing a conversion factor. Now, if there was another way to choose the factor, we could write the entire formula as value * conversion. How would choosing the factor be implemented in this case? Well, one thing we could do is separate the factor selection from the printing by doing it beforehand like this:
def length():
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    if unit == "in" or unit == "\"":
        conversion = 2.54 / 100
    elif unit == "ft" or unit == "'":
        conversion = 30.48 / 100
    elif unit == "yd":
        conversion = 0.9144
    elif unit == "mi":
        conversion = 1.609344 * 1000
    else:
        print("The selected unit is not supported")
        return
    print("{us_value:.2f} {unit} is {si_value:.2f} m".format(
        us_value=value, unit=unit,
        si_value=value * conversion
    ))
This by itself is not very different, and as a side effect we now have to convert everything to meters. The factors have been adjusted to reflect this. However, with a new useful type we can turn this into something much more elegant.
Learning goals: After this section you'll kow what dictionaries are in Python and a couple of different scenarios where they can be used to create elegant and dynamic code (i.e. code that's easy to adjust without making big changes). As another central topic we're looking into the difference between mutable and immutable objects and finally learn why it's important to understand variables as references to values.

Dictionary of Chaos

Dictionaries are
data structures
. Data structures in general are
types
that contain other
values
. Usually the values within a structure should be somehow related. Data structures also have their built-in means for placing values into them and retrieving the values. True to its name, dictionaries do this by word lookup. The words are called
keys
and they can be any immutable types - but most commonly they are
strings
.
Image source 7
Just like words in real dictionaries are connected to explanations or translations, in Python dictionaries keys are connected to values. Whereas keys are usually strings, values can be anything - including other
data structures
! Likewise, the same key can only be present once in a dictionary but there are no such limitations for values. Lookup is one way: only keys can be used to look up values, not the other way around.
A dictionary is marked with curly braces. Anything inside the braces is interpreted as the
dictionary's
definition. The
syntax
requires that key-value pairs are separated from each other with commas, and keys are separated from values with colons. Because dictionary definitions tend to be rather wordy they are very commonly split into multiple lines. Typically splitting is done after the opening brace, and after each comma. The example below might hint at where we are going with dictionaries:
length_factors = {
    "in": 0.0254,
    "ft": 0.3048,
    "yd": 0.9144,
    "mi": 1609.344
}
This example also shows a good convention of
indenting
the key-value pairs by one level. This indentation has no meaning for how the code is interpreted - it just makes the whole thing easier to read at a glance.

Inventonary

One pretty clear use for a dictionary could be a (very) simple inventory management system. Let's make one...
Learning goals: Defining a
dictionary
.
Answer Specification:
Write a definition for a new dictionary. The dictionary has to have the following
keys
and values:
  • "donkey": 15
  • "blue bucket": 0
  • "desperate walrus": 1
Defining this dictionary is best done by splitting it into multiple lines. You can choose the name for the dictionary freely as long as it's a legal Python name. Write the key-value pairs in the given order.

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

Getting a Hold of the Keys

One selling point of
dictionaries
was getting
values
from them by looking up with
keys
. That's cool. How? There's two ways to do this: a common lookup syntax associated with
data structures
and the dictionary get
method
. The common lookup is made by adding a lookup value in square braces to the end of structure (or most commonly a
variable
that contains the structure). For dictionaries the lookup value is a key. E.g. getting the conversion factor for yards from the dictionary we cooked up earlier:
In [1]: length_factors = {
   ...:     "in": 0.0254,
   ...:     "ft": 0.3048,
   ...:     "yd": 0.9144,
   ...:     "mi": 1609.344
   ...: }
   ...:

In [2]: factor = length_factors["yd"]

In [3]: factor
Out[3]: 0.9144
A lookup from a dictionary
returns
the value corresponding to a key, which can then be
assigned
to a variable. Instead of a variable, it can also be used inside a
statement
just like a function call. So, how about replacing the
conditional structure
we recently created with a key lookup...? A key can also be retrieved from a variable:
In [4]: unit = "ft"
In [5]: print(length_factors[unit])
0.3048
Combining these new facts into a brand new length function:
def length():
    length_factors = {
        "in": 0.0254,
        "ft": 0.3048,
        "yd": 0.9144,
        "mi": 1609.344
    }
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    print("{us_value:.3f} {unit} is {si_value:.3f} m".format(
        unit=unit,
        us_value=value,
        si_value=value * length_factors[unit]
    ))
This example also splits the long
method call
line into several lines like we did in an example earlier. The code itself is best understood through an animation:
As neat as this code looks it unfortunately has two (new) flaws: inch and foot cannot be looked up with their symbols; and unsupported user input is not dealt with in any way. The first one is quite easy to solve. As we stated earlier, the same value can be found with multiple keys, so we can just add the two:
    length_factors = {
        "in": 0.0254,
        "\"": 0.0254,
        "ft": 0.3048,
        "'": 0.3048,
        "yd": 0.9144,
        "mi": 1609.344
    }
This example also shows a bit of the dynamism we advertised earlier: we were able to add new features to the
function
just by editing this dictionary instead of having to alter the
conditional structures
in the code (which we completely got rid of anyway).

Sherlock de Bug and The Wrong Key

Python sticks to its habit of throwing out exceptions when you code tries to reach for the non-existent. This also happens when trying to retrieve a value with a key that's not in the dictionary.
Learning goals: What happens when trying a lookup with a
key
that doesn't exist.
Introduction:
We need a dictionary, so let's create one using the example:
In [1]: length_factors = {
   ...:     "in": 0.0254,
   ...:     "ft": 0.3048,
   ...:     "yd": 0.9144,
   ...:     "mi": 1609.344
   ...: }
Answer Specification:
Your task is to try to get a value from this dictionary with a key that isn't there. As usual, we want the exception name as your answer.

Warning: You have not logged in. You cannot answer.
Now that we know that trying to look up with a key that doesn't exist in the dictionary results in an
exception
, the next step is to handle it. If the user's
input
causes an exception we'll just print a friendly error message. At the code's present state, we'll have to put the entire print monster inside the try
branch
. Although the statement is a bit long it's not particularly volatile. There's no real risk of catching the exception caused by something else than we intended.
def length():
    length_factors = {
        "in": 0.0254,
        "\"": 0.0254,
        "ft": 0.3048,
        "'": 0.3048,
        "yd": 0.9144,
        "mi": 1609.344
    }
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    try:
        print("{us_value:.3f} {unit} is {si_value:.3f} m".format(
            unit=unit,
            us_value=value,
            si_value=value * length_factors[unit]
        ))
    except LastTasksAnswer:
        print("The selected unit is not supported.")
Invalid values are still left unhandled - we'll cover that one properly in the next material. Another thing: defining the
dictionary
inside the function is not smart because it's only used for reading values. If it's inside the function it gets redefined every time the
function
is called. It would make more sense to define it in the beginning of the program as a
constant
. In other words, like this (leaving the rest of program out for now).
LENGTH_FACTORS = {
    "in": 0.0254,
    "\"": 0.0254,
    "ft": 0.3048,
    "'": 0.3048,
    "yd": 0.9144,
    "mi": 1609.344
}

def length():
    unit = input("Input source unit: ")
    value = float(input("Input value to convert: "))
    try:
        print("{us_value:.3f} {unit} is {si_value:.3f} m".format(
            unit=unit,
            us_value=value,
            si_value=value * LENGTH_FACTORS[unit]
        ))
    except LastTasksAnswer:
        print("The selected unit is not supported.")
The same can be done for the other functions. We should move on to modifying dictionaries though.

Wordsmithing Dictionaries

A common feature of
data structures
is that they can be modified.
Dictionaries
support adding new
key
-
value
pairs during program execution. Values of keys can also be changed. In order to explore these features, let's create a new function. Imagine a program that processes measurement results from multiple sources. Each result is a dictionary with two key-value pairs: measurement unit and the measured value. E.g.:
measurement = {
    "unit": "in",
    "value": 4.64
}
For further processing it would be better to have all measurements converted to the same unit. The dictionary we just created for the length
function
can be slightly modified to be used for this purpose. The goal is to make a function that converts one measurement to meters. The new function will have one
parameter
. We no longer prompt the measurement and unit from the user because they are read from the dictionary instead, using the lookup we learned previously. Likewise the result will be calculated into a variable instead of printing it.
def convert_to_meters(measurement):
    value = measurement["value"]
    unit = measurement["unit"]
    meters = value * LENGTH_FACTORS[unit]
The only thing left to solve is saving the new values into the dictionary. The way to do it is actually astonishingly similar to what we did with lookups. We already know that the role of a
variable
changes if it's placed on the left side of an
assignment operator
: it will be assigned to instead of using its value. The syntax of key lookup works exactly the same: if it's on the left side of an assignment operator, the value of the key will be replaced with whatever is on the right side:
In [1]: measurement = {
   ...:     "unit": "in",
   ...:     "value": 4.64
   ...: }
   ...:
In [2]: measurement["unit"] = "m"
In [3]: measurement
Out[3]: {'unit': 'm', 'value': 4.64}
This looks rather simple, and isn't really that complicated, but there is one new concept involved:
dictionaries
are a
mutable
type. What's noteworthy here is that new variables are not created at any point when the dictionary is modified - the modification is done directly to the same dictionary. Earlier in this material we said that
strings
are an
immutable
type and that all methods that appear to "change" the string actually return a modified copy. Nothing prevents us from using strings and replace to manage the measurements:
In [1]: measurement = "12.984 in"
In [2]: measurement.replace("in", "m")
Out[2]: '12.984 m'
In [3]: measurement
Out[3]: '12.984 in'
In [4]: measurement = measurement.replace("in", "m")
In [5]: measurement
Out[5]: '12.984 m'
In this example we're first trying to "modify" the measurement but we soon notice that the effect of replace did not stick. Only the fourth line makes a change that actually sticks. However at this point it is no longer the same variable - it's a new one that has the same name. Dictionaries - like other mutable types - are the opposite: operations that modify them usually fiddle with the original directly. When messing around with dictionaries it's worth keeping in mind that they are basically collections of
references
to values. The values themselves are not really inside a dictionary as such - they reside in memory just like any old values. The fact that they correspond to dictionary
keys
doesn't make them special in any way.

Wormhole in a Dictionary

When it comes to mutable objects, the other side of the coin is the more mysterious one. In this exercise we investigate how a dictionary that's been assigned from one variable to another behaves. This continues our inventory saga. This fictional function changes the state of an inventory entry but also needs to conserve its original state for history reasons.
Learning goals: See how
mutable
types differ from
immutable
types.
Introduction:
A
dictionary
is needed once again so let's create one. We'll also create another
variable
where we
assign
the same dictionary. Finally we add 5 to the value of the "count"
key
in the new dictionary.
In [1]: item = {
   ...:     "name": "donkey",
   ...:     "count": 10
   ...: }
In [2]: new = item
In [3]: new["count"] += 5
Answer Specification:
Investigate both dictionaries. After concluding your investigation, write the value of the "count" key in the item dictionary to the answer box.

Warning: You have not logged in. You cannot answer.
If you stumble upon a need to actually have two identical
dictionaries
this can be achieved with the dictionary copy
method
. As the name suggests, it returns a copy of the dictionary. But that's not what we want right now. We specifically want a function that modifies the original measurement. We achieve it like this:
def convert_to_meters(measurement):
    value = measurement["value"]
    unit = measurement["unit"]
    meters = value * LENGTH_FACTORS[unit]
    measurement["unit"] = "m"
    measurement["value"] = meters
Is this missing something (other than exception handling)? This
function
doesn't have a return statement which seems a bit suspect... Except it isn't, this function is precisely what we want. When a
mutable
value is modified the change is written directly into the original area in memory. This means that the change will be reflected to anywhere in code where this dictionary is accessed. We can prove this by implementing a simple
main program
. Pay attention to how we print the measurement twice using the exact same line, and how the
return value
of the
function call
is not assigned to anything.
LENGTH_FACTORS = {
    "in": 0.0254,
    "\"": 0.0254,
    "ft": 0.3048,
    "'": 0.3048,
    "yd": 0.9144,
    "mi": 1609.344
}

def convert_to_meters(measurement):
    value = measurement["value"]
    unit = measurement["unit"]
    meters = value * LENGTH_FACTORS[unit]
    measurement["unit"] = "m"
    measurement["value"] = meters

measurement = {"unit": "in", "value": 4.64}
print("{:.3f} {}".format(measurement["value"], measurement["unit"]))
print("is")
convert_to_meters(measurement)
print("{:.3f} {}".format(measurement["value"], measurement["unit"]))
We can run this program and see that
4.640 in
is
0.118 m
And what about the
exception
handling? It's still possible that the function receives a
dictionary
that contains unsupported units (we're still naive enough to assume all values will be floats). Since we're studying here, let's do this handling in a way that teaches something new while we're at it. If we cannot convert a measurement we're going to tag a measurement with a new key-value pair: key "invalid" with a
boolean value
- more specifically True if we were unable to convert the measurement. Adding a new key is done exactly the same way as modifying the value of an existing one - just like
variables
once again. The exception handling itself is done by putting the lookup itself into try
branch
, error handling in the except branch and dictionary update in the else branch:
def convert_to_meters(measurement):
    value = measurement["value"]
    unit = measurement["unit"]
    try:
        meters = value * LENGTH_FACTORS[unit]
    except KeyError:
        measurement["invalid"] = True
    else:
        measurement["unit"] = "m"
        measurement["value"] = meters
The actual new thing is that there's another way to retrieve
values
from a dictionary: the get
method
. In contrast to the lookup we learned earlier, this method doesn't cause an
exception
when the key doesn't exist. Instead of causing a scene, the get method
returns
a predetermined default value - None if not otherwise defined.
In [1]: measurement_1 = {"unit": "m", "value": 1.0}
In [2]: measurement_2 = {"unit": "donkey", "value": 3.63, "invalid": True}
In [3]: measurement_1.get("invalid", False)
Out[3]: False
In [4]: measurement_2.get("invalid", False)
Out[4]: True
We can add handling of this into the main program for demonstration purpose:
LENGTH_FACTORS = {
    "in": 0.0254,
    "\"": 0.0254,
    "ft": 0.3048,
    "'": 0.3048,
    "yd": 0.9144,
    "mi": 1609.344
}

def convert_to_meters(measurement):
    value = measurement["value"]
    unit = measurement["unit"]
    try:
        meters = value * LENGTH_FACTORS[unit]
    except KeyError:
        measurement["invalid"] = True
    else:
        measurement["unit"] = "m"
        measurement["value"] = meters

measurement = {"unit": "donkey", "value": 4.64}
print("{:.3f} {}".format(measurement["value"], measurement["unit"]))
print("is")
convert_to_meters(measurement)
if not measurement.get("invalid", False):
    print("{:.3f} {}".format(measurement["value"], measurement["unit"]))
else:
    print("Invalid unit")
Running results in
4.640 donkey
is
Invalid unit
This main program is a very artificial example. We just can't provide a more "real" use context without studying the next material first. Either way we've learned the basics of
dictionaries
and
mutable
values here.

Closing Words

In this material we've obtained three essential programming concepts: processing and producing text with
strings
; handling
exceptions
with try-except structures; and most importantly how to control program flow using
conditional structures
. Our programs transformed from doing simple calculations to programs where users can make real choices and get different results based on them. We also discovered that one big part of programming is transforming the so called engineer solutions to results that can be shown to anyone. Functional logic is just a part of programming - user experience is also important.
We also took our first look at
data structures
with
dictionaries
getting the honor of being the first one of them. Since dictionaries are also the first
mutable
type in the material we learned some details about how that separates them from
immutable
types like
strings
.
One noteworthy thing about this material is that in the latter example we routinely left user
inputs
unchecked to keep the code examples from running too rampant. Wherever we prompt numbers from the user we should always have a try-except structure to keep the program behaving. We will return to this topic in the next material and show how to do this without making the code harder to read. Another notable fault with the conversion program is that it has to be restarted after every conversion. This injustice will also be addressed in the future.

Image Sources

  1. original license: CC-BY 2.0
  2. original license: CC-BY-NC 2.0 (caption added)
  3. original license: CC-BY 2.0 (caption added)
  4. original license: CC-BY 2.0 (caption added)
  5. original license: CC-BY 2.0
  6. original license: CC-BY 2.0 (caption added)
  7. original license: CC-BY 2.0 (caption added)
?
  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.
  1. Description
  2. Esimerkit
Avausmoodilla kerrotaan Pythonille (ja käyttöjärjestelmälle) millä tavalla tiedosto avataan. Tiedosto voidaan avata lukemista tai kirjoittamista varten. Oletuksena, eli jos avausmoodia ei erikseen määritellä, tiedosto avataan lukumoodissa ("r"). Kirjoitusmoodeja on kaksi:
  • "w", eli write, joka kirjoittaa tiedoston sisällön puhtaalta pöydältä hävittäen mahdollisesti aiemmin olemassa olleen saman nimisen tiedoston.
  • "a", eli append puolestaan kirjoittaa olemassaolevan tiedoston loppuun.
Molemmat kirjoitusmoodit luovat tiedoston, jos sitä ei vielä ole olemassa.
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.
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.
Siinä missä UNIX-pohjaiset järjestelmät tuottavat \n-merkkejä rivinvaihdoiksi, Windows tuottaa \r\n-rivinvaihtoja, joissa r on carriage return -merkki. Se on kirjoituskoneiden peruja ja tarkoittaa toimenpidettä, jossa kirjoituspää siirretään takaisin rivin alkuun. Yleisesti ottaen tämä on lähinnä asia, joka on hyvä tietää – Python käsittelee molempia rivinvaihtoja kiltisti.
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.
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 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. Esimerkit
Erotin (engl. separator) on merkkijonoihin ja tekstitiedostoihin liittyvä termi. Sillä tarkoitetaan tiettyä merkkiä, joiden kohdilta merkkijono on tarkoitus katkaista, kun se luetaan koodiin. Esimerkiksi, jos merkkijono sisältää tietoja, jotka on tarkoitus lukea listaan, erotin erottelee merkkijonon osat alkioiksi. Koodissa käytetään usein merkkijonojen split-metodia näissä tilanteissa – metodilla voidaan siis pätkiä erottimien kohdilta merkkijono listaksi.
  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.
Exception on yleisimpien poikkeusten pääluokka. Kutsumme sitä Pokémon-poikkeukseksi, koska jos sitä käyttää try-except-rakenteessa, except ottaa kiinni kaikki poikkeukset. Tämä ei ole hyvä asia, koska se tekee vikatilanteiden tulkitsemisen vaikeammaksi sekä ohjelman käyttäjälle, että koodarille itselleen – se ottaa nimittäin kiinni myös ohjelmointivirheet, jolloin et saa mitään hyödyllistä tietoa ohjelman kaatuessa.
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).
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
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).
  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.
  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. Materiaaliesimerkki
  3. Peruskäyttö
Komentoriviargumentti (engl. command line argument) tai -parametri on nimitys lisätiedolle, joka annetaan komennon yhteydessä kun ohjemaa käynnistetään komentoriviltä. Komentoriviargumentit erotetaan toisistaan tyypillisesti välilyönnillä. Esimerkiksi komennossa python koodi.py koodi.py on itse asiassa komentoriviargumentti. Komentoriviargumentteja voi käsitellä Python-koodissa sys-moduulin argv-muuttujan kautta.
  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äsittelijä(funktio) (engl. handler) on funktio, joka on kiinnitetty tapahtumaan siten, että sitä kutsutaan kun tarkkailtu tapahtuma havaitaan. Tämä johtaa siihen, että yleensä käsittelijää ei kutsuta samassa koodissa missä se on määritelty, vaan se toimii takaisinkutsuna. Käsittelijät liittyvät yleensä käyttöliittymä- ja pelikirjastoihin, joissa ohjelman pääsilmukka pyörii kirjaston sisällä ja tarkkailee tapahtumia. Käsittelijät ovat varsinaisen sovelluksen tapa toteuttaa omat toimintonsa tapahtumien kautta. Koska sovelluksen kirjoittaja ei voi vaikuttaa siihen miten käsittelijäfunktiota kutsutaan, sen parametrien ja paluuarvojen tulee vastata kirjaston antamia määrityksiä.
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.
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.
  1. Description
  2. Esimerkit
Metodi (engl. method) on funktio, joka on osa objektia eli objektin ominaisuus, jolla objekti usein muuttaa omaa tilaansa. Metodia kutsuttaessa käsiteltävä objekti tulee kutsun eteen: valinta.lower(). Metodeita kutsutaan myös joskus jäsenfunktioiksi (engl. member function).
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.
  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ä.
Ohjelmointivirhe eli bugi (engl. bug) on virhe ohjelman lähdekoodissa. Bugien seurauksena ohjelma ei välttämättä käynnisty ollenkaan, voi joissain tilanteissa toimia väärin ja joskus aiheuttaa jopa erittäin vakavia tietoturvaongelmia. Huolellinen ohjelmointi ja testaaminen – myös harvinaisilla nurkkatapauksilla – vähentää bugien todennäköisyyttä. Ohjelman havaitun virheellisen toiminnan aiheuttavan koodin etsimistä ja korjaamista kutsutaan debuggaukseksi.
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.
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.
  1. Description
  2. Parametrien valinta
  3. Lisämuotoilu
Paikanpidin (engl. placeholder) on yleisesti tilapäinen merkintä, joka on tarkoitus korvata toisella. Tällä kurssilla sitä käytetään lähinnä merkkijonojen muotoilun yhteydessä. Paikanpidin merkkijonon sisällä merkitään aaltosulkeilla ("Hei {}".format(nimi)). Merkkijonojen paikanpitimissä voi olla lisämäärityksiä kuten näytettävien desimaalien lukumäärä ("Aaseilla on keskimäärin {:.2f} jalkaa".format(keskiarvo)). Paikanpitimien tilalle sijoitetaan format-metodikutsun argumentit, normaalisti esiintymisjärjestyksessä. Ne voidaan kuitenkin myös numeroida tai käyttää avainsanoja.
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. Esimerkit
Poikkeus (engl. exception) on ohjelmointikielessä määritelty virhetilanne. Poikkeuksella on tyyppi (esimerkiksi TypeError), jota voi käyttää poikkeuksen käsittelyssä ohjelman sisällä sekä myös apuna virhetilanteen ratkaisussa. Tyypillisesti poikkeukseen liitetään myös viesti, joka kertoo mistä ongelmassa on kyse. Pythonissa poikkeuksia käsitellään try-except-rakenteilla.
  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.
  1. Description
  2. Esimerkit
Polku (engl. path) on tiedoston tai kansion sijainti kiintolevyllä. Polku voi olla absoluuttinen tai relatiivinen. Absoluuttinen polku sisältää kaikki kansiot aina juureen asti (esim. Windowsissa asemakirjain kuten C:), kun taas relatiivinen sisältää kansiot aktiiviseen kansioon asti (ts. siihen kansioon mistä ohjelma käynnistettiin). Polku esitetään ohjelmointikielissä yleensä merkkijonona, ja polun osat erotetaan kauttaviivalla /. Useimmiten polkuja muodostaessa kannattaa käyttää os.path-moduulin join-funktiota.
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.
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.
  1. Description
  2. Esimerkit
Rekursio (engl. recursion) on yleinen ohjelmointitermi, joka viittaa siihen, kun funktio kutsuu itseään. Rekursio on siis funktiopohjainen tapa luoda toistorakenne, jossa funktio välittää itselleen uusia argumentteja ja käsittelee omia paluuarvojaan. Rekursio on kätevä esimerkiksi puumaisia rakenteita käsitellessä – käsitellään yksi ”oksa” jollain tavalla, ja sitten rekursion avulla käsitellään tästä oksasta lähtevät oksat ja niin edelleen. Pythonissa rekursiota käytetään aika vähän. Osasyynä on sisäänrakennettu rekursiorajoitus, joka asettaa katon sille, kuinka monta kertaa funktio saa kutsua itseään.
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.
Rivinvaihtomerkki (engl. newline, line break, end of line; lyh. EOL) eli "\n" on merkki, joka tulostettaessa tai tiedostoon kirjoitettaessa saa aikaan rivinvaihdon.
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.
A sequence is any value in Python that is a series of things - for instance, string, list and tuple are all sequences.
Matematiikasta tuttu sidontajärjestys (engl. precedence) määrittää sen, missä järjestyksessä lausekkeen operaatiot suoritetaan.
lopputulos = 10 + 2 * (2 + 3)
Yllä olevan koodin lopputulos on 20, sillä ensin lasketaan yhteen luvut 2 ja 3, joiden summa kerrotaan kahdella, ja johon lopuksi lasketaan vielä yhteen luku 10. Esimerkissä korkein presedenssi on siis sulkeilla, toisiksi korkein kertolaskulla ja matalin yhteenlaskulla.
  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.
  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.
Syntaksi (engl. syntax) on koodin kielioppi. Esimerkiksi Pythonin syntaksi määrittää, millainen teksti on tulkittavissa Python-koodiksi. Jos teksti ei noudata koodin syntaksia, sitä ei voida suorittaa. Syntaksi antaa myös koodaajalle tietoa siitä, missä muodossa halutunlainen ohje tulee antaa.
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.
Tallennusformaatti on tiedoston "syntaksi", joka siis kertoo miten data on tiedostoon tallennettu. Tallennusformaatti asettaa rajat sille millaista dataa tiedostossa voidaan esittää. Sen perusajatus on se, että koodissa olevat tietorakenteet voidaan tallentaa tiedostoon jossain muodossa, ja myöhemmin ladata sieltä uudelleen. Tallennusformaatti voi seurata jotain alan standardia (esim. JSON), mutta lopullisesti on ohjelman tekijän vastuulla päättää mitkä tiedot ovat ohjelman kannalta relevantteja ja miten ne on paras esittää.
Tapahtuma (engl. event) on ohjelmointikäsite, jota käytetään yleisesti interaktiivisten sovellusten, jotka pyörivät reaaliajassa, yhteydessä. Näissä sovelluksissa on yleensä pääsilmukka, joka tarkkailee tapahtumia, joita voivat olla esimerkiksi: käyttäjä klikkaa hiirellä, käyttäjä painaa näppäimistön nappia, tietty aika on kulunut jne. Tapahtumiin voidaan kiinnittää käsittelijäfunktioita, jolloin funktiota kutsutaan aina kun tapahtuma havaitaan. Tällä tavalla helpotetaan merkittävästi interaktiivisten sovellusten ohjelmointia, koska itse sovellusta kirjoittaessa ei tarvitse huolehtia siitä miten ruudun tapahtumat tunnistetaan.
Periaatteessa tekstitiedosto (engl. text file) on mikä tahansa tiedosto, jonka sisältö voidaan lukea nätisti tekstieditorilla. Tämän kurssin kontekstissa kuitenkin tekstitiedosto on erityisesti sellainen tiedosto, jonka sisältöä käsitellään tekstinä Pythonissa. Eli siinä missä kooditiedostoja suoritetaan, tekstitiedostoja käytetään datan varastoimiseen ohjelman ajojen välillä.
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.
Tiedostokahva (engl. file handle) on erityinen objekti, jota Pythonissa käytetään avattuun tiedostoon viittaamiseen. Huomattavaa on, että kahva ei ole sama asia kuin tiedoston sisältö, mutta sen kautta voidaan lukea tiedoston sisältö tai kirjoittaa tiedostoon. Tiedostokahva saadaan käyttöön open-funktiolla, jolle määritetään avattavan tiedoston sijainti sekä avausmoodi, jossa se avataan, esim: with open("aasi.txt", "r") as tiedosto: avaa aasi.txt-tiedoston with-lauseessa (jossa tiedostot tulee yleensä avata) siten, että muuttujasta nimeltä tiedosto löytyy tiedostokahva.
Tila (engl. state) viittaa sananmukaisesti ohjelman tilanteeseen. Käytännössä ohjelman tila kattaa kaikki sen tila-avaruuteen (engl. state space) kuuluvat asiat, kuten muuttujien arvot, tiedostoissa olevan datan ja sen, mitä kohtaa koodista sillä hetkellä ollaan suorittamassa. Taattu keino saada aikaiseksi korjauskelvotonta spagettikoodia on käyttää niin kutsuttua globaalia tilaa (engl. global state) – rikos, johon syyllistyvät epäpuhtaat globaaleja muuttujia hyödyntävät funktiot.
Myöhemmillä, ohjelmoinnin käsitteitä formaalimmin tutkivilla kursseilla tutuksi tulevat muun muassa tilakoneet (engl. state machine) sekä tilattomat (engl. stateless) että tilalliset (engl. stateful) ohjelmat.
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):.
  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. Esimerkit
Pythonissa with on hieman muista poikkeava avainsana, sillä se ei ole varsinaisesti ohjausrakenne tai uuden asian määrittely. Tällä kurssilla sitä käytetään pääasiassa tiedostojen avaamisessa, tyyliin with open("aasi.txt") as tiedosto:. Tiedoston luku- tai kirjoitusoperaatiot suoritetaan with-lauseen alla. Kun with-lohko päättyy, Python huolehtii automaattisesti with-lauseessa avattujen tiedostojen yms. sulkemisesta.