Skip to content

cat posts/en/python-lernen-02-werte-und-variablen.md

Learning Python (Part 2): Values and variables

Data types, variables, arithmetic, and f-strings: our adventurer gets hit points and gold, and the dungeon gets a proper status line.

Macro photo: A small pile of gold coins lies on mossy stone slabs, with a cardboard tag reading “gold” leaning against it.

In part 1, we installed Python, tried out the REPL, and wrote our first small program. The dungeon could ask for the adventurer's name and then greet them.

Today our adventurer gets a real state: hit points, gold, and other values that describe how things currently stand. We need to be able to store these values, print them, and change them over the course of the game.

For that, we need two basics: data types and variables.

What is state?

In programming, the term state refers to the current condition of a program or part of it.

Our adventurer's state includes, for example:

  • their name
  • their hit points
  • their maximum hit points
  • the number of their gold coins

State isn't a data type of its own in Python. The term only groups together the values that describe, at a given moment, what's currently going on in the program.

At the start, our adventurer's state could look like this:

name = "Karl"
hp = 100
max_hp = 100
gold = 50

If the adventurer gets hurt or finds gold later on, their state changes.

Values have data types

Every value in Python has a specific type. To start with, these four matter most:

"Karl"  # str: a string
100     # int: an integer
3.5     # float: a floating-point number
True    # bool: a truth value

A str is a string, meaning text. Strings go in quotation marks:

"Karl"
"You enter the dungeon."
"100"

An int is a whole number, an integer:

100
0
-25

A float is a floating-point number. Python code uses a period as the decimal separator:

3.5
0.25
-12.75

A bool is a truth value, a Boolean, and it has two values:

True
False

We'll need Booleans in the next part, when our dungeon has to make decisions.

You can use type(...) in the REPL to check which data type a value has:

>>> type(100)
<class 'int'>
>>> type("100")
<class 'str'>
>>> type(3.5)
<class 'float'>
>>> type(True)
<class 'bool'>

Pay particular attention to the difference between 100 and "100":

100    # a number
"100"  # a string

They look similar, but to Python they're completely different things. You can calculate with the number 100. The string "100", on the other hand, is text that happens to consist of three digits.

This difference is a common source of bugs once input comes into play.

Variables: values with names

Put simply, a variable is a name that refers to a value. You can use that name to get back to the value later:

name = "Karl"
hp = 100
gold = 0

In Python, the equals sign (=) doesn't mean a mathematical equation. It's an assignment.

The statement

hp = 100

means, roughly:

Assign the value 100 to the name hp.

The name can later be bound to a different value:

hp = 100
hp = hp - 25

Python evaluates the right-hand side first. At this point, hp stands for 100, so

hp - 25

results in 75. Then hp is assigned this new value.

So after both statements, hp has the value 75.

Variable names

Variable names should describe as clearly as possible what they stand for:

name = "Karl"
gold = 50
max_hp = 100
verbleibende_hp = 75

A name like x tells you little about its content. With verbleibende_hp (German for remaining HP), on the other hand, it's immediately clear what's meant.

A few rules apply to variable names:

  • They can't start with a digit.
  • They can't contain spaces or hyphens.
  • Digits are allowed, as long as the name doesn't start with one.
  • Names are case-sensitive.
  • Reserved Python keywords such as class, if, or for can't be used as variable names.

Multiple words are usually separated with underscores. This style is called snake_case:

max_hp = 100
gefundenes_gold = 10
verbleibende_hp = 75

These names, however, don't work:

2gold
my gold
max-hp
class

Python would interpret the minus sign in max-hp, for example, as the subtraction operator.

Also, gold, Gold, and GOLD are three different names to Python.

Calculating with numbers

Python has the usual arithmetic operators. You can try them out directly in the REPL:

>>> 10 + 3
13
>>> 10 - 3
7
>>> 10 * 3
30
>>> 10 / 3
3.3333333333333335
>>> 10 // 3
3
>>> 10 % 3
1
>>> 2 ** 10
1024

The operators mean the following:

Operator Meaning Example
+ Addition 10 + 3 gives 13
- Subtraction 10 - 3 gives 7
* Multiplication 10 * 3 gives 30
/ Division 10 / 3 gives about 3.33
// Floor division 10 // 3 gives 3
% Remainder of a division 10 % 3 gives 1
** Exponentiation 2 ** 10 gives 1024

With these numbers, a regular division with / returns a float. That's true even when the division comes out even:

>>> 9 / 3
3.0

Floor division // returns the quotient rounded down:

>>> 10 // 3
3

With positive numbers, this looks at first as if Python just cuts off the decimal places. With negative results, you can see the difference:

>>> -10 // 3
-4

The mathematical result is about -3.33. Rounded down, that becomes -4, not -3.

The modulo operator % returns the remainder of a division:

>>> 10 % 3
1

3 goes into 10 three whole times. That leaves a remainder of 1.

f-strings: putting values into text

In part 1, we joined strings and variables with the plus sign:

print("Welcome, " + name + "!")

An f-string is more readable. You put an f directly before the opening quotation mark. Then you can insert values and expressions into the string in curly braces:

name = "Karl"
hp = 75

print(f"{name} has {hp} hit points left.")

The output is:

Karl has 75 hit points left.

You can use multiple values in one f-string:

hp = 75
max_hp = 100
gold = 50

print(f"HP: {hp}/{max_hp} | Gold: {gold}")

The output is:

HP: 75/100 | Gold: 50

The curly braces can also contain calculations:

hp = 75

print(f"Half of your hit points is {hp / 2}.")

The output is:

Half of your hit points is 37.5.

f-strings are a very handy way to combine text and other values into one piece of output. From now on, we'll use them regularly.

Converting input to a number

The input(...) function always returns a string, even when the player types a number:

gold = input("How many gold coins are you bringing? ")

If the player types 50, gold then contains the string "50", not the number 50.

You can check that with type(...) in the REPL:

>>> gold = input("How many gold coins are you bringing? ")
How many gold coins are you bringing? 50
>>> type(gold)
<class 'str'>

Before you can calculate with it, you have to convert the string to an integer with int(...):

gold = input("How many gold coins are you bringing? ")
gold = int(gold)

After that, gold contains the value 50 of type int.

You can also combine both steps:

gold = int(input("How many gold coins are you bringing? "))

Python works from the inside out here:

  1. input(...) reads the input.
  2. int(...) converts the string to an integer.
  3. The result is assigned to gold.

Without this conversion, you can get surprising results:

>>> "50" * 2
'5050'

Here, Python repeats the string "50" twice. No mathematical multiplication takes place.

Other combinations lead straight to an error:

>>> "50" + 10
Traceback (most recent call last):
  ...
TypeError: can only concatenate str (not "int") to str

If the player types something that can't be interpreted as an integer, you get a ValueError instead:

>>> int("fifty")
Traceback (most recent call last):
  ...
ValueError: invalid literal for int() with base 10: 'fifty'

We'll cover how to catch errors like this and ask the player again for valid input later in this series.

The dungeon, step 2

Our adventurer now gets their first real state. Open the dungeon.py file from part 1 and replace its content with the following code:

# Dungeon—Part 2: Player state
print("You stand before the rusty gate of a forgotten dungeon.")
print("A cold draft blows toward you.")

name = input("What's your name, adventurer? ")
gold = int(input("How many gold coins are you bringing? "))

hp = 100
max_hp = 100

print()
print(f"Welcome, {name}!")
print(f"HP: {hp}/{max_hp} | Gold: {gold}")

# A trap injures the adventurer
schaden = 25
hp = hp - schaden

print()
print("Barely three steps in—and a trap snaps shut!")
print(f"You lose {schaden} hit points.")
print(f"HP: {hp}/{max_hp} | Gold: {gold}")

# The adventurer finds gold
gefundenes_gold = 10
gold = gold + gefundenes_gold

print()
print(f"Between the stones, you find {gefundenes_gold} gold coins.")
print(f"HP: {hp}/{max_hp} | Gold: {gold}")

The abbreviation hp stands for hit points. In max_hp, we store the maximum. So the adventurer starts at 100 out of a maximum of 100 hit points. The German names schaden and gefundenes_gold mean damage and found gold.

The values behind the names

name
hp
max_hp
gold

together make up the current player state.

The empty print() produces a blank line and separates the individual sections of the output.

After the trap, we subtract the damage from the hit points:

hp = hp - schaden

100 hit points become 75.

When the adventurer finds gold, we add the amount found to the gold they already have:

gold = gold + gefundenes_gold

If the player had 50 gold coins before, they now have 60.

Run the program:

python dungeon.py

With the inputs Karl and 50, the output looks something like this:

You stand before the rusty gate of a forgotten dungeon.
A cold draft blows toward you.
What's your name, adventurer? Karl
How many gold coins are you bringing? 50

Welcome, Karl!
HP: 100/100 | Gold: 50

Barely three steps in—and a trap snaps shut!
You lose 25 hit points.
HP: 75/100 | Gold: 50

Between the stones, you find 10 gold coins.
HP: 75/100 | Gold: 60

The dungeon can now store values, change them, and print them as part of its state.

So far, though, the program runs the same way from top to bottom every time. Regardless of the input, the same trap snaps shut, and then the same gold always turns up between the stones.

In the next part, we'll teach the dungeon to make decisions and respond to the player's input.

Pitfalls

  • Calculating with a string as if it were a number. input(...) always returns a string. So if you want to calculate with integers the player types, convert them with int(...).

  • Entering invalid input. int("three") and int("3.5") lead to a ValueError. For input like "3.5", you need float(...) instead.

  • Using a comma as the decimal separator. For number literals and for a direct conversion with float(...), Python expects a period: 3.5, not 3,5.

  • Forgetting the f before an f-string. print("{name}") prints {name} literally. Only print(f"{name}") inserts the variable's value.

  • Mixing up uppercase and lowercase. To Python, gold, Gold, and GOLD are three different names.

  • Appending a number to a string with +. "Gold: " + gold doesn't work if gold is an int. With an f-string, it works without any trouble: f"Gold: {gold}".

Exercises

1. Calculate the approximate year of birth

Also ask for the adventurer's age and calculate roughly which year they were born in. For this exercise, use 2026 as the current year.

Solution
aktuelles_jahr = 2026
alter = int(input("How old are you? "))

geburtsjahr = aktuelles_jahr - alter

print(f"You were born around {geburtsjahr}.")
`aktuelles_jahr`, `alter`, and `geburtsjahr` are German for current year, age, and year of birth. The result is only approximate because we don't check whether the birthday has already happened this year.

2. Use a healing potion

The adventurer has 75 hit points left and finds a healing potion that restores 30 hit points. Their hit points can't go above max_hp.

Use the min(...) function for this:

min(a, b)

The function returns the smaller of the two values.

Solution
hp = 75
max_hp = 100
heilung = 30

hp = min(hp + heilung, max_hp)

print(f"HP: {hp}/{max_hp}")
`heilung` is German for healing. Without a cap, `75 + 30` would give a total of `105` hit points. Since `min(105, 100)` returns the smaller value, `hp` is capped at `100`.

3. Extend the player state

Also give the adventurer a level variable. They start at level 1. Then print the complete state on one line:

Karl | Level: 1 | HP: 100/100 | Gold: 50
Solution
name = "Karl"
level = 1
hp = 100
max_hp = 100
gold = 50

print(f"{name} | Level: {level} | HP: {hp}/{max_hp} | Gold: {gold}")

Going deeper

f-strings can do a lot more than insert variables and calculations. Among other things, they let you align numbers, limit decimal places, and format values in different ways:

f-strings to the max

Next up

The dungeon can store and change values, but it can't make decisions yet. In part 3, we add decisions and loops.

With if and else, the game responds to different situations. Then we build a game loop that lets the dungeon listen to the player's commands over and over.

0 comments

No comments yet. Be the first!