Data Types
Every piece of information in Python, whether it's a number, a word, or a whole collection of items, is stored as a particular data type. This section brings together several of the most important data types you'll use constantly as a Python programmer: numerical types, strings, lists, and dictionaries. By the end, you'll be comfortable creating each of these, understanding what makes them different from one another, and choosing the right one for the job at hand.
This section will help you get comfortable with some of the most common variable types in Python. By the end, you'll understand what kind of information can be stored in numerical types, strings, lists, and dictionaries, and how to create, manipulate, and extract information from each of them.
You'll also be able to create your own examples of integers, floats, booleans, strings, and lists, and describe their key properties. Understanding these distinctions is what allows you to choose the right data type for a given task, which in turn helps you write code that's cleaner, more efficient, and less prone to bugs.
Glossary
Throughout this section, you'll come across a handful of recurring terms. Use the table below as a quick reference whenever you're unsure of a definition.
| Term | Definition |
|---|---|
| Type (also called a class) | A blueprint for a specific kind of data that can be stored in your computer. It describes what an object is and what it can do. |
| Object (also called an instance) | A specific, concrete example of a type that has actually been created and exists in memory. If a type is the blueprint, an object is the finished building. |
Integer (int) |
A Python type designed to store whole numbers, positive, negative, or zero, with no decimal point. |
Float (float) |
A Python type designed to store numbers that may not be whole, i.e. numbers with a decimal component. |
String (str) |
A Python type designed to store a sequence of characters, in a specified order, such as a word, sentence, or phrase. |
| Index | The number used to reference the position of a particular value within an ordered collection, such as a string or list. |
List (list) |
A Python type designed to store a collection of values, of any mixture of types, in a specified, changeable order. |
A quick way to see these terms in action:
# 'age' is an object; its type (blueprint) is int
age = 25
print(type(age)) # <class 'int'>
# 'name' is an object; its type is str
name = "Ada"
print(type(name)) # <class 'str'>
Let's get started. In the next activity, we learn more about types.
Types
In this activity, we take a closer look at types. In Python, every value, expression, and variable is an object, and every object is an example, or instance, of a particular type or class.
It can help to think of a type as a blueprint. A blueprint doesn't just describe what something is, it also describes how Python should store the associated data in memory, and what features and behaviours any instance built from that blueprint will have. For example, every int object supports addition and subtraction, while every str object supports slicing and joining, because that's what the int and str blueprints define.
Python Code Examples
# Example 1
# The result of an expression is itself an object, which is an instance of some type
# The "type" function tells us the name of that type
print(type(1 + 3)) # <class 'int'>
# Example 2
# The value stored in a variable also has a type
a = 1.1
print(type(a)) # <class 'float'>
# Example 3
# We can check the type of any value directly, not just a variable
print(type("words")) # <class 'str'>
# Example 4 (extra)
# Even a boolean value has its own type
is_sunny = True
print(type(is_sunny)) # <class 'bool'>
# Example 5 (extra)
# And so does a list, which we'll explore properly later in this section
print(type([1, 2, 3])) # <class 'list'>
A handy habit to build early on: whenever you're unsure what kind of value you're working with, especially after a calculation or when reading in external data, just wrap it in type() and print the result. It's one of the fastest ways to catch a bug before it causes bigger problems further down your code.
In the next activity, we look at how to identify and use numerical types.
C.3 Numerical Types
Python has three built-in numeric types: integers, floats, and complex numbers. In this activity, we'll focus on integers and floats, since these are by far the two you'll use most often. For anyone curious to go further, there's also an optional extension section covering complex numbers.
Exercise 1: Numerical Types
In this exercise, you'll have a chance to write and test your own code. Please use Anaconda to complete the exercise.
Run your code and save the file. It's also worth making a note of the steps you followed, the results you got, and any errors you encountered along the way, this kind of running log is a great habit for building your understanding over time.
Python Code Examples
# Example 1
# Integers are written and printed without a decimal point, and must be whole numbers
a = 1
print(a)
print(type(a)) # <class 'int'>
# Example 2
# Floats are written and printed with a decimal point
b = 3.1
print(b)
print(type(b)) # <class 'float'>
# Example 3
# Floats can still represent whole numbers, as long as a decimal point is present
c = -2.0
print(c)
print(type(c)) # <class 'float'>
# Example 4
# Division (/) always returns a float, even when both values are integers
print(4 / 3) # 1.3333333333333333
# Example 5
# Adding two integers returns an integer
print(1 + 2) # 3
# Example 6
# Adding two floats returns a float
print(3.0 + 1.0) # 4.0
# Example 7
# Mixing an int and a float in an operation returns a float
# Python automatically "upgrades" the result so no precision is lost
print(2 + 1.5) # 3.5
# Example 8
# The float() function converts a value into a float
print(float(5)) # 5.0
# Example 9
# The int() function converts a value to an integer by rounding toward zero
d = 2.6
print(int(d)) # 2 (not 3! int() truncates, it does not round)
# Example 10
# Calling a function on a variable does not change the variable's own stored value
print(d) # 2.6, unchanged
# Example 11
# The round() function rounds to the nearest whole number (unlike int(), which truncates)
print(round(d + 1)) # 4
# Example 12 (extra)
# round() can also round to a set number of decimal places, using a second argument
pi_estimate = 3.14159
print(round(pi_estimate, 2)) # 3.14
# Example 13 (extra)
# Common arithmetic operators: + - * / // % **
print(7 // 2) # 3 (floor division: divides then rounds down)
print(7 % 2) # 1 (modulo: returns the remainder)
print(2 ** 3) # 8 (exponentiation: 2 to the power of 3)
A quick warning worth flagging early: int() and round() behave differently, and mixing them up is a very common source of small bugs. int(2.6) gives 2 (it simply chops off everything after the decimal point), whereas round(2.6) gives 3 (it rounds to the nearest whole number). Keep this distinction in mind whenever precise rounding matters, for example, when working with money.
Sample Exercise Solution
# Solution Cell 1
# Specify my_number. Set the value to -3.6 for the last part of the exercise
my_number = 10.8
print(my_number)
# Use the int function to create round_down
round_down = int(my_number)
print(round_down) # 10, truncated toward zero
# Use the round function to round to the nearest integer
round_nearest = round(my_number)
print(round_nearest) # 11, rounded to the nearest whole number
# Use the float function to make a float from round_nearest
new_float = float(round_nearest)
print(new_float) # 11.0
Try it yourself: rerun the solution above using my_number = -3.6 instead. Notice how int(-3.6) behaves, does it round toward zero, or away from it? Comparing the two cases is a great way to build intuition for how truncation works with negative numbers.
In the next activity, we look at what a string is and how to use it within Jupyter Notebooks.
C.4 Strings
A string is a sequence of characters, letters, numbers, spaces, punctuation, essentially any text. In this activity, we explore strings in more detail, including how they can be created, stored, manipulated, and accessed in Python.
Exercise 2: Strings
In this exercise, you'll have a chance to write and test your own code. Please use Anaconda to complete the exercise.
Run your code and save the file. It's worth noting down the steps you followed, the results you had, and any errors you ran into.
Python Code Examples
# Example 1
string1 = "Python"
string2 = "is my favourite language"
# Indexing: square brackets with a single number select one character
# Negative indices count backwards from the end of the string
first_string = string1[-3]
print(first_string) # "h" (the 3rd character from the end)
# Slicing: [start:stop:step] selects a range of characters
# Starts at index 1, stops before index 10, taking every 3rd character
second_string = string2[1:10:3]
print(second_string)
# Slicing with an empty start: samples from the very beginning
# Stops before index 3, taking every character (step defaults to 1)
third_string = string2[:3:] + string1
print(third_string)
# len() tells us how many characters are in a string
print(len(third_string))
# Example 2 (extra)
# Strings can be repeated using the multiplication operator
print("ab" * 3) # "ababab"
# Example 3 (extra)
# Common string methods are extremely useful in practice
greeting = " Hello, World! "
print(greeting.strip()) # removes leading/trailing whitespace: "Hello, World!"
print(greeting.upper()) # " HELLO, WORLD! "
print(greeting.lower()) # " hello, world! "
print(greeting.strip().replace("World", "Python")) # "Hello, Python!"
# Example 4 (extra)
# f-strings are a clean, modern way to build strings that include variable values
name = "Ada"
age = 30
print(f"{name} is {age} years old.") # "Ada is 30 years old."
Sample Exercise Solution
# Solution Cell 1
string1 = "Python"
string2 = "is my favourite language"
# The third character from the end of the string is selected
first_string = string1[-3]
print(first_string)
# Every third character beginning with the second character (index 1) is returned
# Sampling stops just before the character with index 10 (the "u")
second_string = string2[1:10:3]
print(second_string)
# The sampled range runs from the start of the string until just before index 3
# Every character in that range is included
third_string = string2[:3:] + string1
print(third_string)
# There are nine characters in the combined string (including the space)
print(len(third_string))
# Solution Cell 2
# Create the string to work with
my_string = "Python is fun"
# Solution Cell 3
# The first character has index zero
print(my_string[0])
# Solution Cell 4
# Leaving the start value blank means we sample from the beginning of the string
# A stop value of 3 means the sampled range covers indices 0, 1, 2
# Leaving out the step value means every character in that range is included
start_string = my_string[:3:]
print(start_string)
# Solution Cell 5
# A start value of -3 means sampling begins three characters from the end
# Leaving the stop value blank means sampling continues until the end of the string
# Leaving the step blank means every character in that range is included
end_string = my_string[-3::]
print(end_string)
# Solution Cell 6
# The two strings are joined together using the concatenation operator (+)
joined_string = start_string + end_string
print(joined_string)
# Solution Cell 7
# A start value of 1 means the first character returned is the second character overall
# Leaving the stop value blank means sampling runs to the end of the string
# A step of 2 means every other character in that range is sampled
alternating_string = my_string[1::2]
print(alternating_string)
A note on indexing: if you're new to programming, Python's indexing can feel unintuitive at first, counting starts at 0, not 1. So in "Python", the letter "P" is at index 0, and "n" is at index 5. Spending a few minutes deliberately experimenting with slices in a notebook cell is one of the best ways to make this click.
In the next activity, we look at how to identify and use lists.
C.5 Lists
In this activity, we turn to lists, another fundamental type in Python. Like a string, a list is a sequence, meaning it's an ordered collection of values. Unlike a string, however, a list can hold values of any type, and even a mixture of different types together, and its contents can be changed after creation.
Exercise 3: Lists
In this exercise, you'll have a chance to write and test your own code. Please use Anaconda to complete the exercise.
Run your code and save the file. As before, it's worth keeping notes on the steps you followed, your results, and any errors along the way.
Python Code Examples
# Example 1
# Create an empty list using square brackets
new_list = []
print(new_list) # []
# Example 2
# We can give a list values straight away when we create it
shopping_list = ["apples", "bananas", "bread", "mushrooms"]
print(shopping_list)
# Example 3
# We can access items in a list the same way we did with strings, using indexing
print(shopping_list[0]) # "apples"
# Example 4
# Negative indices count backwards from the end of the list
print(shopping_list[-1]) # "mushrooms"
# Example 5
# Slicing works on lists just as it does on strings
print(shopping_list[1::2]) # every other item, starting from index 1
# Example 6
# This syntax changes the value stored at a specified index to a new value
shopping_list[0] = "tomatoes"
print(shopping_list)
# Example 7
# .append() adds a new value to the end of the list, extending it by one item
shopping_list.append("grapes")
print(shopping_list)
# Example 8
# .insert() places a new value at a specified position
# Any existing values from that position onward are shifted one place to the right
shopping_list.insert(1, "lettuce")
print(shopping_list)
# Example 9
# len() tells us how many items are currently in the list
print(len(shopping_list))
# Example 10
# The + operator concatenates two lists, producing a brand new combined list
print(shopping_list + ["turnips", "beetroot"])
# Example 11 (extra)
# .remove() deletes the first matching value found in the list
shopping_list.remove("bread")
print(shopping_list)
# Example 12 (extra)
# .sort() rearranges the list's items into ascending order, in place
numbers = [4, 1, 8, 3]
numbers.sort()
print(numbers) # [1, 3, 4, 8]
# Example 13 (extra)
# A list can mix different data types together
mixed_list = ["text", 42, 3.14, True]
print(mixed_list)
print(type(mixed_list[1])) # <class 'int'>
Sample Exercise Solution
# Solution Cell 1
# Create the list with its initial values
cuddly_animals = ["rabbit", "hamster"]
print(cuddly_animals)
# Solution Cell 2
# Use the append method to add the string "rat" to the end of the list
cuddly_animals.append("rat")
print(cuddly_animals)
# Solution Cell 3
# Use the insert method to insert "chinchilla" at the start of the list
# Subsequent items in the list are shifted one position to the right
cuddly_animals.insert(0, "chinchilla")
print(cuddly_animals)
# Solution Cell 4
# Change the value of the second item in the list to "ferret"
cuddly_animals[1] = "ferret"
print(cuddly_animals)
# Solution Cell 5
# Trying to print the item with index 99 raises an error
# This is because the list isn't large enough to contain an item at that index
print(cuddly_animals[99])
# IndexError: list index out of range
# Solution Cell 6
# Similarly, trying to assign to index 99 also raises an error
# You cannot assign to an index that doesn't already exist in the list
cuddly_animals[99] = "gerbil"
# IndexError: list assignment index out of range
Why the errors matter: these two IndexError messages are deliberately included here because they're extremely common when you're starting out, especially once loops are involved. Rather than being something to avoid seeing, learning to read and understand error messages like this is a core programming skill in itself.
In the next extension activity, we look at how to recognise complex numbers.
C.6 Extension: Dictionaries
By the end of this activity, you'll know how to create dictionaries and use their basic functions. Dictionaries are especially useful whenever information is naturally organised as key-value pairs, for example, mapping a name to a phone number, or a product code to its price.
Exercise 4: Dictionaries
In this exercise, you'll have a chance to write and test your own code. Please use Anaconda to complete the exercise.
Run your code and save the file. As always, it's worth noting the steps you followed, your results, and any errors encountered.
Python Code Examples
# Example 1
# Create a dictionary and give it some initial values
# Dictionaries are created using curly brackets {}
# Key-value pairs are separated by commas
# Each key-value pair contains a colon separating the key from its value
atomic_numbers = {"H": 1, "He": 2}
print(atomic_numbers)
# Example 2
# We can add a new key-value pair using item assignment: dict_name[key] = value
atomic_numbers["Li"] = 3
print(atomic_numbers)
# Example 3
# The same item assignment syntax also lets us update an existing value
atomic_numbers["H"] = 0
print(atomic_numbers)
# Example 4
# We access an individual value by placing its key in square brackets
print(atomic_numbers["He"]) # 2
# Example 5 (extra)
# Attempting to access a key that doesn't exist raises an error
print(atomic_numbers["O"])
# KeyError: 'O'
# Example 6 (extra)
# .get() is a safer way to access a value, since it won't raise an error if the key is missing
# Instead, it returns None (or a default value you specify) if the key isn't found
print(atomic_numbers.get("O")) # None
print(atomic_numbers.get("O", "n/a")) # "n/a"
# Example 7 (extra)
# .keys(), .values(), and .items() let us inspect a dictionary's contents
print(atomic_numbers.keys()) # dict_keys(['H', 'He', 'Li'])
print(atomic_numbers.values()) # dict_values([0, 2, 3])
print(atomic_numbers.items()) # dict_items([('H', 0), ('He', 2), ('Li', 3)])
# Example 8 (extra)
# We can loop through a dictionary's key-value pairs directly
for element, number in atomic_numbers.items():
print(f"{element} has atomic number {number}")
A quick comparison worth remembering: a list is best when order matters and you look things up by position (e.g. "the third item"), while a dictionary is best when you look things up by a meaningful label (e.g. "the atomic number of hydrogen"). Recognising which of these fits your data naturally will save you a lot of unnecessary code later on.
Comparing Python's Common Data Types
| Aspect | Integer (int) |
Float (float) |
Boolean (bool) |
String (str) |
List (list) |
Dictionary (dict) |
|---|---|---|---|---|---|---|
| Stores | Whole numbers | Numbers with a decimal component | Logical True / False values |
A sequence of characters (text) | An ordered collection of values | A collection of key-value pairs |
| Example | age = 25 |
price = 9.99 |
is_active = True |
name = "Ada" |
shopping_list = ["apples", "bananas"] |
atomic_numbers = {"H": 1, "He": 2} |
| Ordered? | N/A (single value) | N/A (single value) | N/A (single value) | Yes, character order is fixed | Yes, item order is preserved | Insertion order preserved (Python 3.7+), but items are accessed by key, not position |
| Changeable (mutable)? | No, a new int is created whenever it's "changed" | No, a new float is created whenever it's "changed" | No | No, strings are immutable, any "modification" creates a new string | Yes, items can be added, removed, or changed in place | Yes, key-value pairs can be added, removed, or changed in place |
| Accessed by | N/A | N/A | N/A | Index (position), e.g. name[0] |
Index (position), e.g. shopping_list[0] |
Key (label), e.g. atomic_numbers["H"] |
| Supports slicing? | No | No | No | Yes, e.g. name[1:3] |
Yes, e.g. shopping_list[1:3] |
No |
| Can mix types inside? | N/A | N/A | N/A | No, only characters | Yes, e.g. ["text", 42, 3.14, True] |
Yes, both keys and values can vary in type |
| Common operations | +, -, *, /, //, %, ** |
+, -, *, /, round() |
and, or, not |
+ (concatenation), * (repetition), .upper(), .replace() |
.append(), .insert(), .remove(), .sort() |
.get(), .keys(), .values(), .items() |
| Best suited for | Counting, indexing, whole-number calculations | Measurements, calculations requiring precision (prices, rates) | Conditions, flags, on/off states | Text, labels, messages | Ordered collections looked up by position | Structured lookups by meaningful label |