Data types in Python, explained (With examples)
All the basic Python data types you need to know to get started, how to convert one type to another, type checking, and all about sequences and collections.
Jun 19, 2024 • 14 Minute Read
Data types are foundational concepts of programming. To understand a language well, you’ll need to have a solid grasp of its data types. In this article, I’ll help you build your foundation of Python data types.
Here’s what we’ll cover:
The basics of Python data types
You can think of variables as containers that store your data. The container has a label and a value we can easily see. For example:
name = "Maaike"
The label is name and the value is Maaike. But did you know that it also has a type? Some languages require specifying the type to make it obvious it has one.
Even though we can’t see it, Python gives the variable a type as well.Or more precisely, it gives the value a type. It looks at the value we’re storing and assigns its type. The variable can change type if a value with another type is assigned to the container.
This way of typing is also known as dynamic typing. In this case, the type is a string because the variable stores text.
Here are more examples:
x = 5 # Integer
y = "Hello" # String
z = True # Boolean
If you want to see the type of a value, you can write (or should I say, type):
print(type(x))
In this case, that outputs:
<class 'int'>
You might notice it says class. That brings me to the next point, which is a commonly asked question: Does Python have primitive data types?
Primitive data types in Python
Many languages, such as Java, make a distinction between a primitive type and a reference type. The primitive types are not coming from classes and not stored as objects (reference types) in the memory.
This is different for Python. In Python, all data values are objects. That means Python has no primitive data types and all the types are reference types. However, Python has built-in data types as we saw above.
Python's simple types, like integers and floats, behave similarly to primitives in other languages for efficiency. The distinction between primitive and reference object is mostly academic but important when considering performance and behavior, such as immutability and how data is passed in functions (by object reference).
So which basic types do we have? We distinguish the following types:
- Numeric
- String
- Boolean
- Null and None
We’ll go over each of these below.
1. Numeric integer data type
Let’s start with the integer data type. We’ve already seen it:
x = 5
But there’s more to say about it. What’s unique about Python is the maximum integer value is sort of unlimited. Why sort of? It’s not limited by Python, but it is limited by the memory on your computer. This isn’t typically a problem—it can contain huge values without any issues. For example, it can do this just fine:
y = 234823923988239090823892380980238023
print(y + 1)
Or even:
print(pow(y, 2))
That’s a really big number, but not a problem for Python:
55142275277234290315055922695613570423734577103123816432796061734948529
We can work with binary, octal, and hexadecimal numbers as well. We do this by prefixing the number:
0b for binary numbers
0o for octal numbers
0x for hexadecimal numbers
If you have no clue what I’m talking about, no worries. You don’t need to understand it yet. But to give you an example, the binary number for 4 is 100. To write it like that in Python, we would have to say:
y = 0b100
If you proceed to print y, it will show you the base 10 number, and that’s 4.
2. Numeric float data type
Decimal (fractional) numbers are represented by the float type. For example:
x = 3.4
This is a typical float. Floats have a very funky limitation, but this isn’t a Python problem. It’s simply a problem with how computer memory works. Or more precisely, it's due to the inherent limitations of representing numbers using binary floating-point format. Let’s see what happens when we do this:
print(x + 0.01)
You might think, “Well, I don’t need Python for that. That’s just 3.41.” I hate to break it to you, but here’s what Python says:
3.4099999999999997
This is similar to the following problem: Can you write one third exactly as a floating point?
You might write: 0.333333333333
But that will never be exactly one third. Adding another 3 will make it more precise but never exactly one third. This is a limitation of the base 10 numbers we work with. Similarly, when you express fractional numbers in binary, you lose some precision. This is important to keep in mind when working with values that have to be very precise, such as monetary values or scientific calculations.
We can have more complex numbers as well. And yes, I’m talking about the complex numbers. Let’s look at those next.
3. Numeric complex number data type
Complex numbers are numbers that consist of a real and an imaginary part. Again, don’t worry if you don’t understand complex numbers—you probably don’t need them (yet).
The imaginary part is denoted as a j (lowercase or uppercase, it doesn’t matter). Here’s an example:
c = 2 + 4j
We can get the real and imaginary parts out separately:
c.real
c.imag
4. Boolean data type
The boolean data type is used for values that can be either true or false. These are very important for if statements and other conditional expressions.
Here’s an example:
b = True
if b:
print("It’s true!")
This will print “It’s true” because, well, it is true.
Let’s move on to the string data type.
5. String data type
The string data type is used for holding text values. We can create it with single, double, and triple single quotation marks, and which one you use makes a small difference. We’ll go over each one.
First, when you create a string with single quotes, you can’t always just use single quotes. Sometimes you’ll need both. For example:
text = 'He said: "Hello!"'
If you need single and double quotes, and the single quote is a value, you can escape the single quotes with the escape character (backslash). When a backslash precedes a character, it means it has a special purpose. In this case it means “don’t treat the single quotes as ending the string but as a literal value”:
text = 'He said: "Hello, how\'s it going?"'
When we use the double quotes, we need to escape the pair of double characters in the string:
text = "He said: \"Hello, how’s it going?\""
Normally in Python, a new line means the end of a statement. If you want to have a new line in your code but continue your string, you can do the \ before the return:
text = "Hello, \
how are you?"
This is to make the code more readable. If you display the string, you’ll see it doesn’t hold a new line in itself. It displays:
Hello, how are you?
If you want a new line, you can use the \n on the same line. For example:
text = "Hello, \nhow are you?"
And that prints:
Hello,
how are you?
There’s one more way to create a string, and that’s creating a string with three single quotes. In this string, you can use single quotes and double quotes without an escape character. If you make new lines in that string, they’re interpreted literally—your string actually contains a new line.
Here’s an example:
text = '''He said:
"Hello, how\'s it going?"'''
And that prints:
He said:
Hello, how's it going?
With strings, we can get the individual letters with the square brackets notation. For example:
text = "Blabla"
first_letter = text[0]
Strings are immutable, which means they can’t be changed after being created. You might wonder why we’re able to do this:
text = "Blabla"
text = "Lala"
This doesn’t change the string object that’s holding Blabla. Instead, it creates a new one holding Lala and assigns that to the text variable.
Also, when you concat two strings, nothing gets altered. New objects are created:
text = "Hi"
text = text + " Hello”
This doesn’t change any string object (that’s not possible). But it creates new ones.
And that’s it for the basic data types. Let’s move on to type checking and type conversion.
Type checking
Sometimes you’ll need to check the type of a variable. Maybe you want to verify you’re working with the type you’re working with, or maybe you have no clue at all and you need to check which type it is. Or maybe you’re having a few different options for a parameter, and you need to do a check and a specific action for the different types. In all these cases, you can check the type with the type() built-in function.
num = "5"
print(type(num)) # Output: <class 'str'>
If you don’t like the outcome of the type() function, you can change the type, assuming the value of the variable fits the new type.
Type conversion
Changing the type of a variable is called type conversion. It’s sometimes also called casting.
Here’s how to do it:
num = "5"
num = int(num) # Convert string to integer
print(type(num)) # Output: <class 'int'>
You can convert to other data types as well:
To float with the function float().
To string with the function str().
To Boolean with the function bool().
Here are some code examples to show you they work similar to int().
float_num = "5.0"
float_num = float(float_num) # Convert string to float
print(type(float_num)) # Output: <class 'float'>
text = 5
text = str(text) # Convert integer to string
print(type(text)) # Output: <class 'str'>
And then there are a few more:
list()
tuple()
set()
Lists, tuples, and sets are data types that allow us to store multiple values in one variable. Let’s look at them in more detail.
Sequences and collections
Just like other languages, Python has a way of storing multiple elements in one variable. The data types that can hold multiple elements are referred to as sequences and collections. There are four built-in collection types: list, tuple, set, and dictionary.
Let’s start with the first one on this list: list.
Lists
A list is an ordered collection of items that can be different types within the same collection. Lists are also allowed to contain duplicates. You can modify lists after their creation, which means that lists are mutable. Here’s a little code snippet:
languages = ["Python", "Java", "C#"]
print(languages)
This will output:
['Python', 'Java', 'C#']
You can add to a list with the append function.
languages.append("JavaScript") # Adding an item
print(languages)
It adds the item and will output:
['Python', 'Java', 'C#', 'JavaScript']
We can access the elements of a list by using the index. As usual, the first element has index 0. Here’s how to get the value Python from the list:
print(languages[0])
We can also loop over all the values of the list:
for language in languages:
print(language)
This loops over all the elements in languages and executes the code block for every language. In this case, it prints the language. Here’s the output:
Python
Java
C#
JavaScript
There are two ways to reverse a list. We can reverse the original list with the reverse function.
languages.reverse() # Changes languages to ['JavaScript', 'C#', 'Java', 'Python']
If we don’t want to alter the original list, we have option two: create a new list in the reversed order with slicing.
new_languages = languages[::-1]
This way of reversing stores the reversed list in new_languages without altering the original.
I imagine this weird-looking index needs some explanation. What we’re doing here is called slicing. I’ll explain it briefly, but please don’t worry too much if this is a bit too complicated for you.
Slicing is a way to access a subset of the original. This looks quite complex, but it’s not too hard. Here are the basics.
The slicing syntax is [start:stop:step], where:
start is the index where the slice starts (inclusive)
stop is the index where the slice ends (exclusive)
step determines the step of the slicing, or how many indices are skipped between items in the slice.
If any of these parameters are omitted, they default to the values:
start defaults to the beginning of the sequence
stop defaults to the end of the sequence
step defaults to 1 (meaning no elements are skipped)
In our case, start and stop are omitted—we start at the beginning and stop at the end. So what about that -1? When you use -1 for the step value, it specifies the sequence should be traversed backwards. By itself, -1 tells Python to start at the end of the sequence and move backwards.
There’s one more thing to mention about reversing lists. If all we need to do is iterate over the reversed list, we can do this with the reversed() function like this:
for language in reversed(languages):
print(language)
This prints them in opposite order.
We can also create a list using the list() constructor., which turns the argument into a list:
items = list("123")
print(items)
This might not do what you’d expect. Here’s what it prints:
['1', '2', '3']
It created a list item for every character in the string. You can’t pass in multiple arguments directly. You can pass in a tuple, though, and it will create a list item for every tuple item. Wondering what a tuple is? Let’s talk about that next.
Tuple
Tuples are a different type of collection and similar to lists. Like lists, tuples are an ordered collection of items. These items can be of different types, and duplicates are allowed. But there’s an important difference: Tuples are immutable. After you’ve created them, you can’t change their content. Here’s how to create them:
dimensions = (1080, 1920)
print(dimensions)
As you can see, we use parentheses to create them as opposed to square brackets for the list. If you try to modify an element in the tuple, you’ll get an error like this one:
TypeError: 'tuple' object does not support item assignment
This can be particularly useful if you need a constant set of values throughout your program and want to make sure they won’t be altered.
Sets
Another type of collection is the set. Sets are unordered collections of unique elements. They’re commonly used for membership testing, removing duplicates from a sequence, and performing mathematical operations, such as intersection, union, difference, and symmetric difference.
Here’s how to create a set:
languages = {"Python", "Java", "C#", "Java"} # Duplicates ignored
print(languages) # Notice duplicates are removed
This will show:
{'C#', 'Java', 'Python'}
As you can see, we use the curly brackets for creating a set, and the duplicate value of Java is ignored. We can add elements to sets like this:
languages.add("JavaScript")
If we add an element that already exists, nothing happens. There’s no error, and nothing is added.
Dictionaries
The last built-in collection data type is the dictionary. Dictionaries are special because they hold key-value pairs that are unordered, mutable, and indexed by keys. This makes them incredibly efficient for fast lookups of data. The values can be duplicate, but not the keys. Python wouldn’t know which element you’re trying to retrieve if two keys were duplicate.
Here’s an example of a dictionary:
capitals = {
"Netherlands": "Amsterdam",
"France": "Paris",
"Germany": "Berlin"
}
print(capitals["France"])
This prints Paris.
Dictionaries in Python are dynamic. You can add new key-value pairs any time after they’ve been created. Adding new items or changing the value of existing items in a dictionary is straightforward: Simply assign a value to a key. If the key already exists in the dictionary, the existing value gets updated. If the key doesn’t exist, a new key-value pair is added.
Here's how you can do it:
capitals["Italy"] = "Rome"
# Updating an existing element
capitals["Germany"] = "Munich" # Please note the actual capital is Berlin!
print(capitals)
This code snippet will output:
{'Netherlands': 'Amsterdam', 'France': 'Paris', 'Germany': 'Munich', 'Italy': 'Rome'}
We can also iterate over a dictionary. We can do it several ways depending on what part of the dictionary you need to access (keys, values, or both).
You can iterate over the keys of a dictionary using a simple for loop:
for country in capitals:
print(country)
This will print:
Netherlands
France
Germany
Italy
Of course, you could’ve used the key to access the values:
for country in capitals:
print(capitals[country])
This will print:
Amsterdam
Paris
Munich
Rome
If you need to access the values only, you can use the .values() method on the dictionary:
for capital in capitals.values():
print(capital)
This will print:
Amsterdam
Paris
Munich
Rome
And lastly, to access keys and values at the same time, use the .items() method, which returns each item as a tuple (key, value):
for country, capital in capitals.items():
print(f"The capital of {country} is {capital}.")
As you can see, we need to specify a variable name for both key and value to get easy access to them. This will output:
The capital of Netherlands is Amsterdam.
The capital of France is Paris.
The capital of Germany is Munich.
The capital of Italy is Rome.
And that’s it for Python data types.
Wrap-up
But that’s not totally it for Python collection data types, just this article on general Python data types. Data types are a foundational concept of any programming language. We’ve started with the basics, gone over the simple built-in data types, shown how you can get the type and convert it, and discussed more complex built-in structures, like lists, tuples, sets, and dictionaries.
At this point, you should feel confident about your ability to deal with Python data types. Good luck and have fun coding!
Want to learn more about Python? Check out Pluralsight's Python 3 Learning Path, which can take you from a Python beginner to expert. Additionally, check out our other Python learning courses.