We closed module 1, in From Problem to Algorithm, with a promise: that the title, the assignee and the priority of a task would stop being written by hand inside a print and would become information the program handles. This lesson keeps that promise. The piece that makes it possible is called a variable, and it is, without exaggeration, the concept on which absolutely everything else in the course rests.

Your current easytask.py prints fixed text. If Marta wants to register another task, you have to open the editor, find the line, change the text and save. That is not a program: it is a document that runs. A real program stores data, queries it, modifies it and calculates with it. For that it needs places to put the data and names to refer to it by.

In this lesson you will learn exactly what a variable is, how to create one with the assignment operator =, which names you may give it and which ones you should give it, what the five basic data types in Python are (int, float, str, bool and None), how to find out the type of any value with type(), and what it means for Python to have dynamic typing. At the end you will rewrite easytask.py so that the Solé Bakery task lives in variables.

Contents

  1. From fixed text to named data
  2. What a variable is
  3. Assignment: the = operator
  4. Reassignment and order of execution
  5. Rules and conventions for names
  6. Comments with #
  7. Python's basic types
  8. Inspecting the type with type()
  9. Dynamic typing: what it means in practice
  10. Mutable and immutable: a first intuition
  11. EasyTask: the task lives in variables
  12. Common mistakes and tips
  13. Exercises
  14. Conclusion

  1. From fixed text to named data

Let's bring back the easytask.py you finished lesson 01-04 with:

print("Title:        Sole Bakery logo")
print("Description:  Three proposals in black and white, vector format")
print("Assignee:     Luis")
print("Priority:     high")
print("Status:       pending")

This program has three serious problems, and it is worth naming them before fixing them:

  • The data is trapped inside the text. "Luis" is not a piece of data as far as the program is concerned: it is a handful of letters inside a longer sentence. The program cannot know who the assignee is, cannot compare it with another name, cannot count it.
  • Repeating a piece of data forces you to repeat it literally. If the assignee appeared in four places and the task were reassigned to Nuria, you would have to change four lines. Forgetting one is a guaranteed bug.
  • There is no way to calculate anything. With fixed text you cannot decide whether a task is urgent, nor count how many are pending, nor anything of the sort.

The solution is to separate the data from its presentation. The data is stored under a name; afterwards it is displayed. Like this:

assignee = "Luis"
print(assignee)

Two lines, and it is already a different program. The first line stores the text "Luis" under the name assignee. The second displays whatever is stored under that name. If tomorrow the task passes to Nuria, you change one line and everything that uses assignee is updated.

That is a variable.

  1. What a variable is

A variable is a name that points to a value stored in the computer's memory.

It is worth pausing on the word points, because it is the key. Many people picture a variable as a box containing the value. That image is acceptable at first, but the correct image in Python is a different one: the value lives somewhere in memory, and the variable is a label stuck to that value. The label contains nothing; it points.

flowchart LR
    subgraph names["Names (what you write)"]
        A["assignee"]
        B["priority"]
        C["estimated_days"]
    end
    subgraph memory["Memory (where values live)"]
        X["'Luis'"]
        Y["'high'"]
        Z["3"]
    end
    A --> X
    B --> Y
    C --> Z

Three practical consequences follow from this, and they will save you confusion later on:

  • A name points to a single value at a time. If you make it point to another one, it stops pointing to the previous one.
  • Several names can point to the same value. It is not a rare case: it happens all the time.
  • Using the name is the same as using the value. When you write print(assignee), Python follows the arrow, finds "Luis" and works with that.

And there is a fourth consequence, more philosophical but very useful: the name is for you, not for the machine. The computer does not care whether the variable is called assignee or x7. Whoever reads the program six months from now — probably you — will care a great deal.

  1. Assignment: the = operator

Creating a variable in Python is as simple as this:

title = "Sole Bakery logo"

The structure is always the same:

name = value

The = symbol is called the assignment operator, and it works from right to left: first whatever is on the right is evaluated, and the result is associated with the name on the left. It is important to internalise that order from the very beginning.

Read it mentally as "becomes" or "points to", never as "is equal to". And here we reach a point that confuses almost everybody at the start.

Why = is not mathematical equality

In mathematics, x = 5 is a statement: it declares a fact that holds. In Python, x = 5 is a command: make the name x point to the value 5.

The difference is perfectly clear in this line, entirely valid in Python and impossible in mathematics:

counter = 0
counter = counter + 1
print(counter)   # displays 1

Mathematically, counter = counter + 1 would be absurd: no number equals itself plus one. As a command, it makes perfect sense:

  1. The right-hand side, counter + 1, is evaluated. Python looks at what counter is worth right now (0) and adds one: the result is 1.
  2. That result, 1, is assigned to the name counter, which stops pointing at 0 and starts pointing at 1.
Aspect In mathematics In Python
What = is A statement of equality An assignment command
How it reads "x is equal to 5" "x becomes 5"
x = x + 1 A contradiction, it has no solution A valid statement: it increments x
Can it be reversed? Yes: 5 = x means the same thing No: 5 = x is a syntax error

That last point is a good mental check: in Python, a name always goes on the left of the =; never a value. Writing 5 = x produces the error SyntaxError: cannot assign to literal.

To compare two values and ask whether they are equal there is another operator, ==, with two signs. You will see it in detail in Operators and Expressions. For now hold on to the distinction: one = assigns, two == compare.

  1. Reassignment and order of execution

A variable can change its value as many times as you like. That is called reassignment, and it is where the name "variable" comes from: its value varies.

status = "pending"
print(status)      # pending

status = "completed"
print(status)      # completed

After the second assignment, the name status stops pointing at "pending" and points at "completed". The old value is lost: there is no way to recover it unless you stored it somewhere else.

flowchart LR
    A1["status"] -.->|"before"| V1["'pending'"]
    A2["status"] ==>|"after"| V2["'completed'"]

From this comes a rule that governs the reading of any program: statements run in order, from top to bottom, and the value of a variable at a given point in the program is the one given by the last assignment before that point.

Check it with this example, which is worth tracing mentally before reading the answer:

assignee = "Luis"
assignee = "Nuria"
print(assignee)

It displays Nuria. The first line does not "get lost" nor "clash" with the second one: it runs, and then the second one replaces it. It is exactly the same logic as the desk check you practised in lesson 01-05, and it is still the best tool for understanding a fragment of code: write down in a table the value of each variable after each line.

Line Statement assignee afterwards
1 assignee = "Luis" "Luis"
2 assignee = "Nuria" "Nuria"
3 print(assignee) "Nuria" → prints Nuria

One important detail: a variable must exist before it is used. If you try to display a name you have not assigned anything to, Python complains:

print(priority)
NameError: name 'priority' is not defined

Read it calmly: "the name priority is not defined". It almost always means one of two things: either you forgot the assignment line, or you wrote it after using it, or there is a typo in the name (priority versus prioirty). Python's error messages are informative; get fond of them as soon as you can.

  1. Rules and conventions for names

There are two levels here, and it is best not to mix them: the rules, which if you break them the program does not start, and the conventions, which if you break them the program works but you give yourself away as a beginner.

Mandatory rules

Rule Valid Not valid
Letters, digits and underscore only title_2 title-2, title 2
Cannot start with a digit task1 1task
Case sensitive Title and title are two different variables
Cannot be a reserved word entry if, for, class, None

The reserved words are the ones Python uses for its own syntax. There are about 35: False, None, True, and, as, assert, break, class, continue, def, del, elif, else, except, for, from, global, if, import, in, is, lambda, not, or, pass, raise, return, try, while, with, yield... You do not need to memorise them: any decent editor colours them differently, and that change of colour is the signal that the name is off limits.

Technically Python 3 accepts accents and non-ASCII letters in names (año = 2026 works). Do not use them. They are awkward to type, they break on different keyboards and no professional project uses them.

Style conventions

Python's conventions are collected in a document called PEP 8, which is the language's style reference. These are the three you need right now:

1. snake_case: lower case and underscores. Words are separated with _, everything in lower case.

estimated_days = 3           # correct in Python
estimatedDays = 3            # Java or JavaScript style, not Python
EstimatedDays = 3            # in Python this is reserved for classes (module 7)

2. Meaningful names. The best name is the one that makes the comment explaining it unnecessary.

Bad So-so Good
x days estimated_days
t text task_title
p prio priority
a, b, c value1, value2 assignee, status

A good criterion: if you have to scroll up to look at the assignment to remember what a variable holds, the name is bad. And do not fear long names: pending_tasks_for_luis is better than ptl. It is written once and read a hundred times.

3. Constants in UPPER CASE. When a value must not change during execution — a rate, a limit, a fixed piece of text — it is named in upper case with underscores:

STUDIO_NAME = "Alba Studio"
MAX_TASKS_PER_PERSON = 10

Watch out for a subtlety that surprises people coming from other languages: Python does not prevent you from changing a constant. STUDIO_NAME = "something else" would work without a word of protest. Upper case is a convention, a warning to the humans reading the code: "do not touch this". The discipline comes from the programmer, not from the language.

  1. Comments with #

A comment is text that Python ignores completely when running. It serves to explain something to the person reading the code.

They are written with the hash sign #. Everything from # to the end of the line is ignored:

# Details of the task Marta has just handed to Luis
title = "Sole Bakery logo"
priority = "high"         # high / medium / low

There are two ways of using them, both visible above: on a line of their own, to explain the block below, and at the end of a line of code, to clarify that particular detail. In this second case, PEP 8 asks you to leave at least two spaces before the #.

A word about good use, without going on at length because documentation has its own lesson in Documentation and Comments: a comment must explain why, not what. This adds nothing:

priority = "high"         # assigns high to priority

This does:

priority = "high"         # the client hands out leaflets next week

Comments also serve to temporarily disable a line while you are testing something, without deleting it. In most editors, Ctrl + / comments and uncomments the line where the cursor is.

  1. Python's basic types

Every value in Python belongs to a data type. The type determines what can be done with that value: two numbers can be subtracted, two pieces of text cannot; a piece of text can be put in upper case, a number cannot.

These are the five basic types you will be working with in this module:

Type Full name What it is for Literal examples
int Integer Quantities without decimals 3, 0, -7, 1250
float Decimal (floating point) Quantities with decimals 3.5, 0.0, -2.75, 19.99
str Text string (string) Text of any length "Luis", 'high', ""
bool Boolean True or false True, False
None Null (type NoneType) Absence of value None

Let's take them one by one, because each has its own detail.

int: whole numbers

They are written without quotes and without decimals. They can be negative and have no practical size limit in Python.

estimated_days = 3
completed_tasks = 12
difference = -2

Do not use thousands separators, neither dot nor comma: 1.250 is not one thousand two hundred and fifty, it is the decimal 1.25. If you need readability, Python allows the underscore: 1_250_000 is a valid integer and reads better.

float: numbers with decimals

They carry a decimal point, not a comma. This is mistake number one for anyone programming in a language that uses the comma:

hours_spent = 7.5      # correct
hours_spent = 7,5      # NOT a decimal: Python understands something else

A warning that will save you bewilderment later on: float values are approximations. The computer stores decimals in binary and some numbers have no exact representation:

print(0.1 + 0.2)      # displays 0.30000000000000004

It is not a flaw in Python: it happens in almost every language. For what we are doing here it is irrelevant, but remember it if you ever program calculations involving money.

str: text strings

They go between quotes, single or double, either is fine, as long as you open and close with the same ones:

assignee = "Luis"
priority = 'high'

A piece of text can contain spaces, numbers and symbols. And watch out for this, because it is a constant source of confusion:

age_text = "3"        # this is a str: the character three
age_number = 3        # this is an int: the quantity three

They look the same and they are not. With 3 you can do arithmetic; with "3" you cannot. This distinction will be the heart of the lesson Type Conversion and Validation.

There is also the empty string, "": text with no characters at all. It is not the same as None, nor as a space " ".

bool: true or false

It has only two possible values, and they are written with the first letter capitalised: True and False. Not true, not TRUE, not Yes.

completed = False
is_urgent = True

Booleans are the basis of every decision the program will make from module 3 onwards. Storing the state of a task as completed = False is far more useful than as status = "pending", because a boolean can be evaluated directly.

None: absence of value

None represents that there is no value. It is a type with a single possible value, and it is also written with an initial capital.

due_date = None       # not yet agreed with the client

It is different from 0, from "" and from False. 0 is a quantity, "" is text with no characters, False is a negative answer; None means "there is nothing here yet". In EasyTask we will use it, for example, for a due date that has not been set yet: it is not an empty date, it is that there is no date.

  1. Inspecting the type with type()

Python comes with a tool for asking what type a value is: the type() function.

title = "Sole Bakery logo"
estimated_days = 3
hours_spent = 7.5
completed = False
due_date = None

print(type(title))
print(type(estimated_days))
print(type(hours_spent))
print(type(completed))
print(type(due_date))

Output:

<class 'str'>
<class 'int'>
<class 'float'>
<class 'bool'>
<class 'NoneType'>

The word class is Python's internal vocabulary (types are classes, something that will make sense in module 7); for now look only at the name between quotes.

type() is your best ally when something does not work as you expect. Compare these two cases, apparently identical:

days_a = 3
days_b = "3"

print(type(days_a))    # <class 'int'>
print(type(days_b))    # <class 'str'>

When printed separately, both display 3 on screen. But one is a number and the other is text, and they behave in radically different ways. When a program does something inexplicable with a piece of data, the first thing to do is print its type(). That reflex will save you hours.

A point of vocabulary, so that you can speak precisely: type() is a function, and the parentheses are the way of "calling" it, passing it a value. You have already used another function, print(). How they work inside and how to create your own is the subject of module 4.

  1. Dynamic typing: what it means in practice

In lesson 01-03 we saw that Python has dynamic typing. Now we can see what that means with code in front of us.

In a statically typed language such as Java or C, when you create a variable you declare its type and that type is fixed forever:

String assignee = "Luis";        // Java: assignee will ALWAYS be text
assignee = 5;                    // error: it does not compile

In Python nothing is declared. The type is determined by the value assigned, and it changes if you assign another value of another type:

value = "Luis"
print(type(value))   # <class 'str'>

value = 5
print(type(value))   # <class 'int'>

value = True
print(type(value))   # <class 'bool'>

Python does not complain at any point. Let's insist on the important nuance: the type belongs to the value, not to the name. The variable is a label, and a label can be stuck today to a piece of text and tomorrow to a number.

Aspect Static typing (Java, C) Dynamic typing (Python)
Is the type declared? Yes, compulsory No
Can the type change? No Yes
When is a type error detected? At compile time, before running At run time, when the line is reached
Advantage More safety, errors caught early More speed and flexibility when writing

And here is a piece of advice that is not optional: the fact that Python lets you change a variable's type does not mean you should. A variable called estimated_days that sometimes holds 3 and other times "three" is an inexhaustible source of bugs. The professional discipline is clear: one name, one purpose, one type. If you need something else, create another variable.

  1. Mutable and immutable: a first intuition

There is a distinction worth planting now, even though its full scope arrives with the lists of module 5.

Some values in Python are immutable: once created, they cannot be modified. Numbers and text strings are. When it looks as though you are modifying them, what you are really doing is creating a new value and repointing the label.

Look at this example:

priority = "high"
priority = "medium"

It is tempting to think that the text "high" has been transformed into "medium". It has not. What has happened is that a new value, "medium", has been created, and the label priority has stopped pointing at the first one to point at the second. The text "high" has not changed; it is simply that nobody is looking at it any more.

flowchart LR
    P["priority"] -.->|"stops pointing at"| A["'high'<br/>(still exists,<br/>unchanged)"]
    P ==>|"now points at"| M["'medium'<br/>(new value)"]

You can check it with id(), a function that returns a unique identifier of the value in memory. If the value were the same one modified, the identifier would stay the same; if it is a new value, it changes:

priority = "high"
print(id(priority))      # e.g. 140234...816

priority = "medium"
print(id(priority))      # a DIFFERENT number: it is another value

(The actual numbers vary on every run and on every computer; the only relevant thing is that they are different.)

And now the practical consequence, which does matter from today:

original_assignee = "Luis"
assignee_copy = original_assignee

original_assignee = "Nuria"

print(original_assignee)      # Nuria
print(assignee_copy)          # Luis

assignee_copy is still worth "Luis". The second line made it point at the same value as original_assignee, but the third line repointed only original_assignee; the other label stayed where it was. With immutable values this always works intuitively: reassigning a variable never affects the others.

Concept Meaning Types you have seen
Immutable The value cannot be modified; reassigning creates a new one int, float, str, bool, None
Mutable The value can be modified "in place" Lists and dictionaries (module 5)

Every type in this lesson is immutable, so for the moment you live in the easy world. Keep the idea in mind: when you reach lists, where copying does not behave like this, you will know exactly what is changing and why.

  1. EasyTask: the task lives in variables

Let's get to what we promised. We rewrite easytask.py so that the five pieces of task data — the five we defined in requirement R1 of lesson 01-01 — stop being written inside the print calls and become variables.

Open your easytask.py and replace the contents with this:

# easytask.py - Alba Studio
# Version 0.2: the task data lives in variables

# --- Fixed program data (constants by convention) ---
APP_NAME = "EasyTask"
VERSION = "0.2"
STUDIO = "Alba Studio"

# --- Task data ---
title = "Sole Bakery logo"
description = "Three proposals in black and white, vector format"
assignee = "Luis"
priority = "high"           # high / medium / low
completed = False           # boolean: True once it is finished
estimated_days = 3          # integer
hours_spent = 7.5           # decimal
due_date = None             # not yet agreed with the client

# --- Screen output ---
print("=== EASYTASK - Alba Studio ===")
print("")
print("Title:")
print(title)
print("Description:")
print(description)
print("Assignee:")
print(assignee)
print("Priority:")
print(priority)
print("Completed:")
print(completed)
print("Estimated days:")
print(estimated_days)
print("Hours spent:")
print(hours_spent)
print("Due date:")
print(due_date)

Run it with python easytask.py. You will see the card, now on two lines per item.

Let's go over the decisions taken in that code, because none of them is accidental:

  • APP_NAME, VERSION and STUDIO are in upper case because they are constants: they do not change during the program's execution.
  • completed is a bool, not the text "pending". It is a deliberate choice: a boolean represents a yes/no better and will be evaluable directly once the conditionals arrive. Notice the name too: completed reads as a statement that is either true or false, which is exactly how a boolean should read.
  • estimated_days is an int and hours_spent a float. Days are counted whole; hours admit halves.
  • due_date is None, not "". It is not an empty date: it is that there is no date yet. The difference is semantic and it matters.
  • The comments explain what the name cannot say: the values allowed in priority, or the reason for the None.

Now the real improvement. Change these two lines:

assignee = "Nuria"
priority = "medium"

Save, run and check that the card reflects the changes. You have modified two lines of data and have not touched a single one of the lines that display the information. In the previous version you would have had to edit the text inside the print calls. That separation between data and presentation is one of the most profitable ideas in the whole trade.

What still grates

Let's be honest about the limitations of this version, which are the script for the next three lessons:

Current limitation Solved in
Each item takes two lines and the card is ugly; you cannot mix text and variable in a single print Input and Output
Nothing can be calculated: neither whether the task is urgent, nor how much is left Operators and Expressions
The data is still written in the code: for another task you have to edit the file Input and Output
Nothing stops you writing priority = "supermegaurgent" Type Conversion and Validation

Four problems, four lessons. Let's take them in order.

Common Mistakes and Tips

Confusing = with ==. One assigns, two compare. Writing priority = "high" when you meant to ask whether the priority is high does not raise an error: it changes the variable's value silently. It is one of the hardest bugs to spot precisely because nothing complains.

Using a variable before assigning it. NameError: name 'x' is not defined always means the same thing: that name does not exist yet at that point in the program. Check that the assignment is written, that it comes before, and that there is no typo in the name.

A typo in the name when reusing it. assignee and asignee are two different variables as far as Python is concerned. The second will give a NameError, or worse: if by chance it also exists, your program will use the wrong data. Let the editor's autocomplete write the names for you.

Forgetting the quotes on a piece of text. assignee = Luis (without quotes) makes Python look for a variable called Luis and fail with NameError. If it is text, it goes between quotes. Always.

Writing decimals with a comma. price = 19,99 is not a decimal. Python interprets the comma as a separator and creates something that is not a number. In Python decimals take a dot.

Writing true or false in lower case. In Python they are True and False, with an initial capital. NameError: name 'true' is not defined is the warning.

Putting a number between quotes by accident. days = "3" is text, not a number. It looks identical when printed and behaves in a completely different way. When in doubt, type().

Single-letter names. An x will seem perfectly clear while you are writing it and a hieroglyph three days later. The only tolerated exception is loop counters, which you will see in module 3.

Using reserved words as names. If the editor colours your variable name the same way it colours if or for, change it.

Tip: try things in the REPL. Before writing something in the file, try it in the interactive interpreter (plain python in the terminal, as you saw in 01-04). Assign, print, check the type(). It is the fastest way of turning a doubt into a certainty.

Tip: name first, program afterwards. When you tackle a new problem, first write the list of pieces of data involved and give them names. Half the design of a program is deciding which variables exist.

Exercises

Exercise 1: Spot and fix the errors

The following program contains six errors. Find them, explain each one and write the corrected version.

1title = "Book fair poster"
assignee = Nuria
priority = 'high"
hours = 4,5
completed = false
print(title, assignee, priority, hours, completed, status)

Exercise 2: Types and tracing

a) State the type of each value without running anything:

Value Type
"Marta" ?
12 ?
12.0 ?
"12" ?
True ?
None ?
"" ?
"True" ?

b) Trace this program in a table (one row per line, one column per variable) and say what it prints:

total_tasks = 8
done_tasks = 3
total_tasks = 10
pending = total_tasks
done_tasks = 5
print(pending)
print(done_tasks)

Exercise 3: Nuria's task card

Write a file nuria_card.py that stores the data of this Alba Studio task in well-named variables and displays it on screen:

  • Title: Poster for the book fair
  • Description: A2 format, two colour versions
  • Assignee: Nuria
  • Priority: medium
  • Not completed yet
  • 2 days of work are estimated
  • 3.5 hours have been spent on it
  • The due date has not been agreed yet
  • The client for this task is not recorded yet

Requirements: use the most appropriate type for each item (not everything as str), name the variables in snake_case and meaningfully, include an upper-case constant with the studio's name and add at least two comments that carry real information. Finish the program by printing the type() of three variables of different types.

Solutions

Solution 1.

The six errors:

No. Line Error Why
1 1title = ... Name starting with a digit Python rule: names cannot start with a number
2 assignee = Nuria Text without quotes Python looks for a variable Nuria and does not find it → NameError
3 priority = 'high" Mismatched quotes It opens with a single quote and closes with a double one → SyntaxError
4 hours = 4,5 Decimal with a comma In Python the decimal separator is the dot
5 completed = false Boolean in lower case In Python it is False, with an initial capital
6 print(... status) Non-existent variable status has never been assigned → NameError

Corrected version:

title = "Book fair poster"
assignee = "Nuria"
priority = "high"
hours = 4.5
completed = False
status = "pending"            # it was missing before being used

print(title)
print(assignee)
print(priority)
print(hours)
print(completed)
print(status)

Note: the original print passed several values separated by commas. That is valid in Python and is studied in Input and Output; here we have split it into several print calls so as not to get ahead of ourselves.

Solution 2.

a) Types:

Value Type Remark
"Marta" str Between quotes → text
12 int No decimals, no quotes
12.0 float The dot makes it a decimal even though it is worth twelve
"12" str Between quotes: it is the text "12", not the number
True bool Initial capital
None NoneType Absence of value
"" str Empty string: it is still text
"True" str With quotes it is text, not a boolean

The three interesting rows are 12 versus 12.0, 12 versus "12" and True versus "True": they look the same on screen and they are not.

b) Trace:

Line Statement total_tasks done_tasks pending
1 total_tasks = 8 8
2 done_tasks = 3 8 3
3 total_tasks = 10 10 3
4 pending = total_tasks 10 3 10
5 done_tasks = 5 10 5 10

It prints 10 and then 5.

The key is line 4: pending receives the value total_tasks had at that instant (10, because line 3 had already changed it). It is not left "linked" to total_tasks: if that variable changed later, pending would still be worth 10. An assignment copies the value of the moment, it does not establish a permanent relationship.

Solution 3.

# nuria_card.py - Alba Studio
# Card for a task assigned to Nuria

STUDIO = "Alba Studio"        # constant: it does not change during execution

title = "Poster for the book fair"
description = "A2 format, two colour versions"
assignee = "Nuria"
priority = "medium"           # high / medium / low
completed = False             # will become True once it is delivered
estimated_days = 2
hours_spent = 3.5
due_date = None               # pending confirmation with the organisers
client = None                 # the job came through the association, no client assigned

print("=== TASK CARD ===")
print(STUDIO)
print("")
print(title)
print(description)
print(assignee)
print(priority)
print(completed)
print(estimated_days)
print(hours_spent)
print(due_date)
print(client)
print("")
print("--- Types ---")
print(type(title))            # <class 'str'>
print(type(estimated_days))   # <class 'int'>
print(type(completed))        # <class 'bool'>

Justification of the types chosen:

  • title, description, assignee and priority are text: str.
  • completed is a yes/no: bool. It is preferable to storing the text "pending".
  • estimated_days is a whole quantity: int.
  • hours_spent allows half hours: float, with a decimal dot.
  • due_date and client have no value yet: None, not "".

And the final check prints <class 'str'>, <class 'int'> and <class 'bool'>.

Conclusion

You have taken the step that turns an executable text into a program. You now know that a variable is a name pointing at a value in memory; that = does not state an equality but commands an assignment, always evaluating the right-hand side first; and that reassigning a variable simply moves the label to another value, without affecting the other variables that pointed at the previous one.

You know the rules for names (letters, digits and underscore; not starting with a number; no reserved words) and, more importantly, the conventions that separate the professional from the amateur: snake_case, meaningful names and constants in UPPER CASE. You have mastered the five basic typesint, float, str, bool and None — you know how to inspect them with type() when something does not add up, you understand what Python's dynamic typing implies and why it is best not to abuse it, and you have a first intuition of immutability that will be very useful when the lists arrive.

And easytask.py is now at version 0.2: the five pieces of data of the Solé Bakery logo task live in variables, and changing the assignee is a matter of editing one line of data, not the code that displays it.

But for now the program only stores information; it does nothing with it. It cannot say whether the task is urgent, nor how long is left until delivery, nor what percentage of the job Luis has done. For that you need expressions: combining variables and values through operators to produce new results. That is exactly the subject of the next lesson, Operators and Expressions, where your variables will stop sitting still and start calculating.

© Copyright 2026. All rights reserved