We start with an introduction to an Interactive Development Environment and to the basic concepts of programming with the Python language. Then, we introduce how data is stored and represented within computers, and how primitive data types are used by Python to represent data within programs. We then learn more about how data is stored and collected by Python, how strings and tuples are stored and managed in Python, and what the common operators are for manipulating these data types. Finally, we learn how to create a simple function that outputs a string to the computer console.
Hello and welcome back. In this lecture I'm going to introduce you to the Python data types, lists, sets and dictionaries. Now lists, sets and dictionaries are very important and you need to have a good grasp in understanding of how they are used to solve and address different data collection programming requirements. So the objective of this lesson will be to introduce you to each of the standard Python collection data types which are lists, sets and dictionaries, and to provide you with useful demonstrations of how to implement and code with each of these. With this in mind, we'll not only demonstrate and walk you through how each of these collection types are used but we'll also highlight the different problems they address. Okay, so let's get started. Consider the following scenario. You have a list of cities that your company is going to operate from. And you're wondering how should I represent and store these values within the Python program. You could start out with each of these cities stored in individual strings. But how would you manage, maintain, and retrieve them at runtime? The answer to this question is the concept of lists and the corresponding data type list. So lists are usually used for one dimensional data sets and they are mutable meaning that the items within a list object can be changed after they'd been initialized. We'll talk more about mutability later in the lesson. But for now we'll continue our discussion on how a list is used to solve a requirement of managing a collection of cities.
A list can contain data of different types, but more often than not the tendency is to use a list to contain data of the same data type. In our presented scenario we are storing a list of city names. So we want to store those names as strings within our application, in this case we would create a variable name cities and initialize it with a list of city names as you see here on the slide. So let's jump back into our terminal and demonstrate some quick examples of working with Python lists. Here I'm using the PyCharm IDE and I'm going to launch the embedded Python console which is where I will demonstrate using and coding with Python lists. Now the simplest list would be just an empty list. An empty list is represented with two square brackets, the opening and closed square bracket. In this case I'm assigning it to the variable A. Next a non-empty list is assigned here to the variable B could contain multiple and different data types such as an integer followed by a string and Boolean. And finally a float. Now this is still considered a valid list regardless that the data types associated with the values are different.
The next thing to consider is how to address and retrieve items back out of this list. To start with we'll consider the first item in list B. The first item within any list is always addressed with the index position zero. So here we can see that the item at index position zero in list B is indeed the value one. If you want to address the last item in a list, then you can use a negative index to navigate backwards. For example you can use minus one to reference the last element in your list, And this is a great example of how Python is very flexible. So to summarize again quickly, the first element in a list starts at position zero, and the last element starts from minus one. Therefore in the example presented here, if you wanted to retrieve the item containing the value string, you could calculate the index starting from the front of the list, that is at position zero, and move forward or right by adding one. Or alternatively you could start from the end of the list and move right or backwards, that is starting at position minus one and subtracting two from it to end up with an index value of minus three which is the same position within the list. Okay, now let's consider the concept of slicing a list. So to slice a list we use a colon at the index as demonstrated here. This indicates that we are interested in everything starting from minus three all the way through to the end of the list which, in this case, extracts the value string, true, and the float 2.3. And this actually returns a new list. I can also generate the exact same slice, but this time by slicing in the positive direction using one and colon as seen here.
Next let's move on and consider what happens when you attempt to add an item to an existing list by using the addition operator. As you can see here, you cannot simply concatenate items in the list in this manner since Python doesn't know how to evaluate the additional operator in the context of a list. So instead the correct way of adding and mutating a list is to use the append method. We perform an append operation to add an additional item into the list. Let's now reexamine list B and see what it now contains. As you can see the new test item has been added to the end of list B. You can also do an insertion on a list using the insert method. Here we are inserting the string myinsert into list B at index position two. So again when we reexamine list B, we can see that the new item has indeed been inserted at position index two. And all existing items have moved forward or right by one position. We can also determine length of a string. In this case the length of our original empty list A is zero. And likewise the current length of list B is six. You can also mutate lists by performing a replacement. For example we can use the slicing operator to replace this portion of the existing list with the items defined in this list. Reexamining list B again we can now see that the single item string has been replaced with the values replace one and two. Just to clarify here, the slicing configuration just used was 1:2. What this means is that we start at index position one and move all the way forward to ending index position, which, in this case, is position two.
The ending index position tells us where to stop. However it is not selected as part of the slice. Therefore the resulting slice is just the item at index position one which, in this case, was the item containing the value string. This is then replaced with the new items, replace one and two. You can also use the replace method with an empty list which, in this case, would result in a deletion of the values in the slice like so. Alternatively you could achieve the same result by using the inbuilt delete function which deletes each of the items in range from the starting index all the way through but not including the ending index. This is demonstrated here. Keep in mind that each time we mutate the list, the index positions of each item within the list may be changed. Moving on the next concept I want to highlight is that of multidimensional lists. So what do I mean by multidimensional I hear you ask. Well, if we were to create a brand new list name C such that this list contains the existing lists A and B, then this will result in a list of lists like this. Here the first lists at index position zero is our original empty list A. And the second list at index position one is our updated and current list B. So this demonstrates the concept of building a multidimensional list. Here we can retrieve the first list by using index zero on list C. And likewise we can retrieve the second list by index one. Finally we can retrieve any item from the second list by again using an indexer and in this case we are using index one again. And this time, as expected, we retrieve the value myinsert. Now what would you expect if we attempted to append a list to itself? Would you think that would be possible? Now in this example we are appending the list C to itself. And as you can see it's very possible. So exactly what just happened? Well under the hood, Python has created an infinitely nested list but is clever enough through the use of pointers to ensure that this type of nesting doesn't explode or error out at runtime. We have ended up with list C containing list C, containing list C and so on and so on. Now we can continue to index and retrieve items from list C as per normal.
For example if we retrieve the item at index position two like so, this returns list C again. The three dots inside the square brackets are used to intelligently denote a self-reference, or that this item is a pointer back to itself. Next if we expand on this example and get the item at index position one on the item at index position two, then the results in the current list B can be seen here. So we can continue drilling down using this type of navigation. Here we are retrieving the item located at index two then one, then one which happens to be the value myinsert. All right, now let's try and attempt to grab the item at index position three in the current list C. As expected this results in an index error exception being raised which is a very common error associated when navigating lists. Okay, let's clean up our Python terminal here. And in review you should now understand what a list is, how they can be created, what they can contain, and how you can navigate them. One final characteristics of lists I'd like to cover off which gives us a good segue into the next collection type that we will review which is sets is that lists can contain multiple identical values. As can be seen here, we can repeatedly append the value one to the end of list B. When we now reexamine list B we can see that it indeed does contain multiple values of the number one. So the point here is that if you require a collection that must manage and maintain more than one occurrence of the same value, then using a list will provide you with this requirement. However, if you have a requirement where you need to maintain an unordered collection of only unique items, then you should use the Python collection data type called a set. In Python sets are created by either using the inbuilt function Set or by using the curly brackets as seen here. In the first example set A is created as an empty list. In the second example, set B is created and populated with several initial items, some of which are non unique. Here we are repeating the item one several times. Now since this collection has been declared intentionally as a set, what should we expect as the outcome of a set to be after its initialized. As you can see here, the resulting set has the following items. One, 2.3, and the value string. So from this here are a few things we need to point out. First the items in this set are all unique and there are no repeats. Secondly the insertion order has not been maintained. Instead it's changed. And finally if you've observed closely, you may have noticed that the Boolean item true has actually disappeared. So why is this so?
Well, it is based on the fact that the Boolean value true equates to the numerical value one. And under the hood a Python set maintains and manages the uniqueness of items by using hashes. And in this case the hash of both one and true are the same. So the key characteristic of a python set is that it enforces uniqueness on items within itself. Sets also reorder themselves when they are created as a performance optimization service. So lists on the other hand respect the insertion order. But this is definitely not the case with sets. So when are sets useful then? A good example is say when you want to maintain a list of cities. In this case it doesn't make any sense to have duplicate city names. Unlike lists, sets do not support the concept of indexing for retrieving items out of the set. This is related back to the fact that sets drop duplicate values and reorder themselves using hashing techniques so as to be optimized for lookup operations. If you need to have those in alphabetical order, you should use the built in sorted method. If you want to determine if an item exists within a set, then you can use the in keyword. Here we are testing to see if the item string is in the set B. And in this case it expectedly evaluates it to be true. We can actually use in to also determine membership on lists. For example we can check to see if the item string is still a member of the list at position C1. In this case it evaluates that to be false. So let's repeat this process but this time for the item test. And as you can see this time, you can see that the evaluation is returned as true. So this is an important technique for how we can test for membership of existence of items within sequences, collections such as sets and lists and also strings for that matter. Okay, moving on now, let's talk about a different type of scenario and how we can model data using the data type dictionary. Now previously we talked about lists and how lists consist of items that are ideally semi-associated with each other. And in that case of a list of cities, we wanna produce them as a list because we might bind them to a dropdown menu on a webpage for example. Now after lists we then review the concept of sets where within a set you can model uniqueness. Now the final collection data type that we want to introduce to you today is that where we have an associative relationship. Say for example we may want to know the kind of country that a city belongs to.
Say for example you might need to maintain that the city New York is associated with the country US. And the city London is associated with the country United Kingdom. In an online web application, this type of data model might be used to auto populate a country field on what city the user selects or enters for example. Now the data type that we use in this case is called a dictionary. And a dictionary consists of key value pairs. The key portion has the same kind of characteristics that you expect from a set, that is each key defined needs to be unique and not duplicated. Values on the other hand are just an association of some data associated with the key. To retrieve values from the dictionary, you do so by using that key. Say for example, say I want to obtain the country associated with the city New York. Then I would provide the key New York to the dictionary, and the dictionary would return me back associated values which in this case would be the country US. When working with dictionaries, keys can be of any data type. For example strings, integers, and or Booleans, all are valid key types amongst others as well. Now one of the important characteristics of data to be used for keys is that the data must be immutable. Now, let's jump back into our PyCharm embedded Python terminal and demonstrate working with dictionaries. To start off with, let's create and initialize an empty dictionary named A. Notice again here the use of curly brackets which were used also when we created sets. Using empty brackets actually creates an empty dictionary, not a set. So if you recall when we created an empty set, we actually needed to use the inbuilt set function to do so. Now, let's create another dictionary assigned to the variable B. But this time we will populate it with several key value pairs. The first key value pair will be A and a 1. And the second value pair be B and 2. The third and final key value pair will be C and 3. Now, this results in a legitimate dictionary. I can now retrieve the various values from this dictionary by using the various keys. For example here I am retrieving the value assigned to the key A which is expectedly the value 1. I would get the other associated values if I were to use the other keys B and C.
So next let's change and update the value assigned to the key A by changing it to the string anything. Now when we reexamine dictionary B, you can see that the value associated with key A has indeed been updated to that new value. So this demonstrates that dictionaries are mutable. In terms of mutability, dictionaries behave similarly to lists but are not like sets which are immutable, okay? Now, if we want to add a new key value pair to an existing dictionary, we do so like this. Here we are adding in a new key which is the number 15. And it is going to be mapped to the value 5. If again we reexamine our dictionary, we can see that the new key value pair has been inserted at the end. Now if we want to obtain a list of all the keys we can simply call upon list and pass in the dictionary like so. Here you can see that the result is a list of just the keys by themselves. Now, how would I use this? Well, instead of maintaining a separate list of just city names, you could instead establish a dictionary with key value pairs for city names and country names respectively. Then to grab just the names of the cities you can call the list and pass in the dictionary. The result returned will be just the city names which you can easily bind to a dropdown menu item. An end user could select from this list and then you could use the selected value to grab keys against the dictionary and then grab the associated country mapping against their key. Again these are just simple examples to demonstrate how to use the various collection types and related features to address particular requirements. It is also possible to delete and remove key value pairs from an existing dictionary. To do so use the inbuilt delete function like this. Here we're passing in the dictionary B together with the value 15. Now when we reexamine the dictionary, you will see that the associated key pair has been removed. And finally you also need to test for existence. So to do that we again use the in keyword like so. In this first example we are testing whether the dictionary contains the key C, which it does, and so expectedly returns true. If we instead test for the key D, it also expectedly returns false indicating that the key does not exist in the current dictionary. Okay, that concludes this lecture. We now should understand what, when, and how lists, sets and dictionaries are used. Lists, sets and dictionaries are very important data types. And in this lecture we've reviewed and demonstrated how they can be used to solve and address different data collection programming requirements. Okay, go ahead and close this lecture and we'll see you in the next one.