 So, welcome back to the Introduction on Python Programming Course. This is chapter one. In this chapter, we will look at some high-level overview of what Python is and how it works and what basic syntax constructs are that we should understand. So, what better way is there than to start with an example? So, imagine that I give you the following task. I give you a list of numbers. And your job is to give me the average of all the even numbers in that list. So how would you go about this? Well, probably you would first ask me some questions. You would ask, what kind of numbers are in this list? Is it whole numbers? Is it decimal numbers? Is it negative numbers? How many of them are there? Okay. So, I will narrow down the task a little bit. I will tell you that the task is, I give you the numbers 1 to 12 and you should give me the average of all the even numbers. So then you say, well, what's the point? I don't need to write a program to get to the solution. I can do this by hand. You know, there are six even numbers in the numbers from 1 to 12, so I can just take them, add them up, and then divide them by six, and I got the average. And I say, well, that's of course true. But what about if I gave you a list with 10,000 numbers where every number is some number between positive 1 and positive 1,000, and I asked you to do the same thing, but then you would maybe revert to Excel or some other spreadsheet software. That's, you know, in order to do that, I would need to give you the data in this format. Let's say it's one column in a spreadsheet. And then maybe you are an Excel wizard, so maybe you know how you could solve this using several, you know, columns of transformations of one column, and maybe you can solve the problem. But I will show you a way here as, you know, how you can solve this problem with just a little bit of Python code. So let's look at the example. Here's a list. And I chose the list from the numbers of 1 to 12, and I did not put them in order here so that we can, you know, not, so that we do not simply assume that the numbers are ordered, because that would also be helpful information in one way. So let's look at this list and let's solve this problem with Python. So here you have the list of the numbers, of the 12 numbers, and what I do here is I write an equal sign and something that I call numbers. So with a little bit of imagination, we can believe that this is a way of how we can create a list with those 12 numbers and assign them to a variable called numbers. That's what it looks like. So let's execute this code cell. And nothing happens. So how do we know if Python has understood this code? Well, we just ask it for, hey, Python, do you know what numbers is, what do we do? We just type the word numbers just as we wrote it as the variable in the assignment above here. We write it again. And then Python indeed confirms that all the numbers seem to have been stored. And the second cell seems to have something called an output. The first cell doesn't. So it seems like in the first cell, we are putting something into the memory. And in the second cell, we are reading something out of the memory. So that's what we at least presume, think of what's going on here. So now how can we use this list in numbers to calculate the average of all the even numbers in the list? So here's our first program, which does exactly that. So this code is a bit lengthy. So we will take some time to take it apart and to analyze how the program works. But let's first just run it. And so we run it. And again, we don't see any output here. So why is that? Well, at the end in the last line of this code, I assigned to a variable called average, something that I call total divided by count. And as before, I store in this cell, I store something in the variable average. And now I want to read it out. So just do it as we did before. I ask Python, hey, what is average? And Python tells me it's 7.0. That seems reasonable. So if I average all the even numbers between 1 and 12, 7.0 seems to be a realistic outcome. So let's check the code and analyze what it does. So how do we usually calculate an average? Well, an average is just the sum of all the individual observations divided by the number of observations. Therefore, we have to sum something up. How do we do this? Well, we initialize two variables that I call count and total. And we set them both to zero. And then here, we see some pros, some English comment that basically explains to us what we are doing. It says, we initialize the variables to keep track of the running total, which is the variable total, and the count of all the even numbers. And we start with the value zero for both of them. And then we enter something that we will soon call a so-called for loop. So whenever we see the word for, that means some piece of code is executed several times in a row. In this case, some code is executed once for every number in the list. So the list was called numbers, plural, so that is here. So it seems like we are kind of looping over the numbers list one by one. So in every iteration of the loop, we get back a number singular, some other variable that is pointing to the individual number or one individual number in the list. And then we see that the code that is below this four line is indented. So we have here four spaces. And then the second and third line below the four line, we have actually eight spaces. And so what that means is this four line means we do something repetitively. And then this code, because it is indented, is the code that we are executing repetitively. In contrast, after the four line, we calculate the average by total divided by count. And this is in the same level of indentation as the four line. That means this last line is not executed repeatedly. It's only those three lines that are indented that are repeated. So let's analyze a little bit more. So the next line of code, it reads like this. If number percent sign to double equals zero, what is that? This is like the first example that is not so intuitive, maybe. But luckily, we are given a comment that explains to us what this line does. And it says, only work with the even numbers. And then we see that the code below that is indented one more level. So we have here an indentation of four and then eight. So it's a one more level of indentation by four space characters. So in other words, this code seems to only be executed whenever we hit an even number. In other words, the if line here checks for an individual number in the numbers list to be even. And if so, it executes code. And if not, it does not execute the code. So what code do we execute for every even number in the list? Well, first, we execute this line. And this line reads like this. Count equals count plus one. Just by the way this formulated, we actually know that the way we treat it, the single equal sign here must have been correct because the single equal sign cannot be read as what we know it from math. In math, the single equal sign means the left side is equal to the right side. It's a statement of truth. It's like saying both sides are equal. That's a fact, so to say. However, if you read this line in this way, we would see that count is equal to count plus one. And this cannot be true because if we subtract count on both sides of the equation, we would end up with zero is equal to one, which is not possible in math. So in other words, this also confirms that the way to read lines where we have a single equivalence sign, a single equal sign, we just check the right-hand side first and do the commands on the right-hand side first. And then we get a result. And the result is then stored in the variable by the name of the left-hand side. And in this line here, what we do is we read out the odd value of count, which starts to be zero. We add one to it and we store it in count again. In other words, this is a counter. We increment it by one whenever we hit an even number. In other words, at the end of the day, count will be six once we go down here because this follow will be looping 12 times and six times, we will hit an even number. And so six times, we will add one variable that is initialized at zero. So count will be six eventually. The second line here, what does that do? Well, this is where we keep track of the running total. So remember, total is set to zero and then whenever we hit an even number, what we do is we just add this number to the odd total and the odd total plus the number that we are currently looping over will be set to the new total. In other words, that just calculates the running total. At the end of the day, total after the follow will be the sum of all the even numbers in this list and count will be the number of even numbers in the list. And then we divide one by the other and that's just the definition of an average. And 7.0 is the correct result if you do the calculations by hand. So that's our first example. So what have you learned so far? We have learned how we can create numbers. We have learned how we can collect numbers in a list and we have seen how we can execute some code repetitively. We have seen an example of a condition. So some code is only executed if some condition is fulfilled. And then we have also seen a difference that sometimes a code cell does not produce an output like here, the upper cell does not produce an output. And the lower cell does produce an output. In fact, it's just us asking Python, give me the value of average. So the natural question asks, when do we see output in a Jupyter notebook? So to give you another example, we have seen text before in the introduction chapter and text is anything that is written between the double quotes here. So we have double quotes in the beginning and double quotes at the end. And then the word or the sentence hello world, that's our first text data thing, whatever that is at the moment. And then we have another text which we see which is on its own line and it's also between double quotes. If I execute this cell, I only see the last line as the output. And don't be confused that whenever we see text as a return value as an output, there are single quotes and we use double quotes when we define text. So that's just a convention. So double quotes and single quotes in this regard work absolutely the same. They are perfect substitutes in this book. I tend to use the double quotes as the convention. This has some other reasons that you will then learn once you read chapter six. But don't be confused, it's the same. But what we don't see is the hello world. So the hello world seems to be gone. And at the end of today's chapter, we will talk about what an expression is in Python and the rule for output is this. We only see as output the last expression of a line of code. So here, the last expression, the last line of code is just I am feeling great, which is why we see that. Whenever we want to see more output, so whenever we have a code cell that is a bit longer and we want to see some intermediate result, we want to print it out, then we will just use Python's print function. We've seen print before as well. So what does print do? If I execute this, it prints out the text we give it to. So note that the parentheses in this example here, that's what we will call later the call operator. And the call operator means print is a function and we call the function. Calling is another word for executing this function and we express the idea of calling by writing open and closing parentheses. And within the parentheses, we pass in whatever we want the function to work on. And in this case, we want the print function to print out this text. And note, there is no out here, right? So in other words, I just said that the rule is that Jupyter Notebook will return to you as output the last expression in a code cell. Since there is no output here, the print function here is really not an expression. It's kind of like it's something else. And we will come back to that at the end of today's chapter because we need to learn some other things in order to understand this fully, but just note with print, we can always print out intermediate results. So let's go on. Python, like basically any software that exists, can be used just as a fancy calculator. And that's basically what a computer is. A computer, any computer, a laptop, a web server, your phone, whatever. At the end of the day, they are just hardware that can execute software. And you know what from your early childhood on, from high school, when you wanna do some calculations in exams, usually you use an old-fashioned calculator. And also you have calculators on your mobile phones. So you know what is a calculator. And at the end of the day, any software, any software language is also, at the end of the day, just a fancy calculator. And that's also true for Python. So let's do some arithmetic with Python. So let's ask Python, what is 77 plus 13? I ask it and Python tells me, well, it's 90. So here we see we get an output as well. It would be kind of weird if we wouldn't get an output here, but just note that if we had more than one addition in this code cell, we would only see a result of the last one. So whenever you can do plus, you should also do minus, right? And this, of course, also works for Python. So in order to subtract two numbers from another, we just use the minus sign that we have on the keyword. Keyword. And those two, the addition and the subtraction, these are two examples of what we would call a binary operator. So first, an operator, if any special symbol here, like the plus and the minus, that makes Python do some specific operation. That's why it's called an operator. And a binary operator is just the operator that takes two operands. So we have one operand on the left side, the first operand, and we have a second operand to the right-hand side. And of course, from school, you remember that the minus sign basically has two meanings. The first meaning is we do subtraction, that's what we see here. And the second meaning is we just use the minus sign to mean a negative number. So by writing minus one, what Python actually does is Python reads this as one and creates the one in memory. And then it gives the number one, the number positive one to the minus operator that's the unary operator. Unary operator because it only takes one operand. And then the unary operator takes the plus one and makes it a minus one and then returns to us the minus one as the output. So we can use the minus with just one operand or two. This is not really surprising for you, I guess. But at the end of the day, it's kind of a big deal because there's something called syntax, so which is very strict rules as to how a computer works. And if you develop a programming language, you have to actually teach the programming language that the minus operator can actually be used in two different ways. So let's go on, after addition and subtraction, we also wanna do multiplication, how do we do that? Multiplication in many programming languages and in Python also being one of them is done with the so-called asterisk symbol. So sometimes we would also say it's a star symbol, it's formally called an asterisk. And that's what we use for multiplication. So we don't use the dot that we remember from school. We also don't use an X or something, it's just the asterisk. So two times 21 is of course 42. Now after multiplication comes division. So what is division? Division means we have two numbers and we divide the first by the second. And in this example, we have two whole numbers, 84 and two and let's divide them and I get back 42.0. So that's actually the first example here where I get back a decimal number. If I go back one slide, there are no decimal numbers. So whenever I add or subtract two whole numbers, I get back a whole number and here I divide one whole number by another whole number and I obviously don't get back a whole number, I get back a decimal number with the decimals being all zeroes of course, but nevertheless it's a decimal number and we will see some implications of that soon. If you don't want that, if you don't want to get back a decimal number, you just use two slashes. So 84 divided by two gives us back 42 still. Now the number is returned, it does not have a decimal. And so that's the double slash and the double slash is sometimes called the integer division operator or sort of the floor division operator. And the term floor division operator may be coming from the fact that if I divide 85 by two, what should I get back? 85 divided by two is of course 42.5. However, if I require the double slash operator to always return a whole number, what should it return? Should it return 42? Should it return 43? Or should it maybe raise an error because it says, well, you can't do that with a whole number. So let's see what Python does. Python gives us back 42 and that's where the integer division operator receives its other name, the floor division operator, because it seems like we are rounding down. So out of 42.5, which is the exact result of 85 divided by two, we end up with a 42. So if we rounded the way that we learned rounding in school, it should be 43 actually. So it seems as if no matter what the decimal is, is if we get back decimal zero or decimal one or a decimal nine, it will always be rounded down. However, that is unfortunately not true. So if for example, I divide negative 85 by two, I get back negative 43. So I now can tell you what the rule is for this operator, the rule is if you divide two integers with the integer division operator, you get back an integer that is rounded towards negative infinity. And that means if we're dividing two positive numbers, this is as if we rounded down. However, if we divide a negative by a positive number, then we round also towards negative infinity, which means we get a negative 43, which means an absolute value we are rounding up actually. So we need to be careful here a little bit. Usually it's not so important because usually when we do math, we will work with the single slash the normal division operator anyways, because we don't care if we get back a decimal with a dot zero. But sometimes this will be important. And then you have to know how the operator behaves in edge cases. Now we've seen two different kinds of division. And now we'll see a third way of division. So that's the percentage sign. That's the sign that we saw in the introduction example today. And we didn't quite understand what it does. So now here is what it does. The percentage sign, the percentage operator is also called the model operator. And model operator is basically the kind of division that you learn in early elementary school, maybe early high school, where you divide one number by another and it doesn't work. You know, it's not a perfect division. So you are left with some rest and the rest is what the model operator returns. So in other words, 85 divided by two is 42 and the rest of one. And the rest of one is then returned to us. So now, since we are at a business school, the question is, why would I care about this operator? Is this operator actually useful for people that wanna solve management problems? The answer is it's super useful and we will see many, many applications of the model operator throughout the entire lecture. But for now, it's sufficient to know that if we model divide a number by two, then if there is a rest of zero, then we know that the number must be even. And this is exactly what I exploited when I wrote the first example in this chapter today. If you divide something by two and there is no rest, we know it's an even number and that's how we identified the even numbers. In other words, if there is one, then the number is not even. The second application of the model operator is when I divide two integers and want to know, can the first integer be perfectly divided by the second one? So in the example, I have 49 divided by seven and of course, 49 is perfectly divisible by seven, which is why I get back zero. So in other words, if I get back zero, it also means the second number divides the first number perfectly. If I don't get back zero, any other number then zero will imply that the number is not perfectly divisible. So and it does not have to be one, of course. So let's say I divide by five. Now I will get a rest of four and the four indicates that the number is not perfectly divisible. That is two different applications of the model operator. A third one would be, let's say we are given a three-digit number, seven, eight, nine, and I want to extract digits from the right. So for example, I want to get the nine out of the seven, eight, nine. How do we do that? I'm moderately divided by 10. This is the way to extract digits out of any number from the right. Of course, if I want to extract two digits, I'm moderately divided by 100 and I get back 89. So we already see that even though as business students we may not be super familiar with the model operator, we already see there are some things that we can do with it and we will see many more applications of the model operator. So let's go on. Now that we've covered division, the next operator we want to cover is exponentiation. So we want to raise two to the power of three. How do we do that in Python? Well, we write it with a double star, a double asterisk. So two double asterisk three is two to the power of three and this is eight. Note that in some other programming languages there is another operator in use which looks like this. And this has the name Carrot operator if you want to search for it on the web and the Carrot operator also exists in Python. So if I run this set again, I get back a one. This is of course not two risen to the power of three. However, it is a valid operator. So you must not confuse double asterisk with the Carrot sign here and we will keep the double asterisk here. Okay, so now that we have five different arithmetic operators we want to put them together into bigger expressions and whatever we do that the question is in what order are the operators executed? So here I say three double asterisk two times two. So this could either mean three raised to the power of two and then the result, which would be nine would be multiplied by two to be 18. The other interpretation could be we multiply the two first to get four on the right hand side and then we raise three to the power of four to get something bigger than 18. However, we do get 18. And so there are two explanations for that. The first one is that we just execute this expression from left to right in which case we would end up with 18. However, Python is smart enough to know how we human think. So in other words, Python does not give us back 18 because it evaluates the code here from left to right but it does give us back 18 because it knows that the exponentiation operator the double asterisk always has to go before we use the single asterisk. And whenever you end out just use parentheses just like in math. So this makes it a bit more explicit. It does not make your code smaller. It's, I mean technically when Python reset it's like probably microseconds smaller, slower here because it has to also process the two parentheses but it's really not a big deal. And so just put it in there and make your code more readable and also be sure that if you put the parentheses somewhere else you get a different result. And yeah, that's all you need to know about operators. So we summarize the arithmetic operators. They work just like as a calculator. They look a little bit different. We have several ways to do division and also the order of precedence works just like in math and in math it's called Pempta's rule. So parentheses go first, exponentiation go second, multiplication and division go third and then last go addition and subtraction and for the last two pairs it doesn't make any difference in what order we do that. Okay, so that's some basic Python. So now we can work with numbers. The question now that we want to look at is what happens in memory? You know, as business people that want to get prepared for data science courses you may wonder why should I care what happens in my computer's memory? The question, the answer is because sometimes when you write bigger programs and at the end of the day you will, there's a good chance that you will make mistakes that you don't understand and you would easily understand if you just knew what happens in memory. So for you as students it may be a little bit tedious in the beginning to learn about a computer's memory but it's absolutely worthwhile because once you get to realize problems that you want to model then this helps you to write programs that are less buggy and also more memory efficient. So when you want to prepare yourself for a course in data science you also have to prepare the topic of big data. So what do you do when you work with data that does not fit into your computer's memory and in order for you to write programs that are memory efficient you have to know how the memory works. So how does the memory work in Python? Well, Python is what is called an object-oriented language and what is object orientation? Object orientation is just a paradigm by which Python organizes the memory for us. In lower level languages like C for example we would have to do everything that Python does for us ourselves. Luckily we don't have to but still object orientation is the concept by which Python does it. So we will look at now an example of some very easy code and see what happens in memory and then with this example that is about to come I will tell you three words, three concepts the concept of an object, the concept of a type and the concept of a value and note that these three words mean totally different things. However, people mess them up all the time and in order to write code that really works I think you should also train yourself a bit to use technical terms with a very precise meaning. So let's look at the example. Let's execute the next line of the next code cell. The next code cell consists of three lines. So first we set a variable A to 42 then we set a variable B to the decimal 42.0 and then we set a variable C to some text. So I have now already executed the cell. So let's see what happened in memory when I did that. So how does Python read this code cell? Well first it executes the code cell line by line so the first line goes first and whenever Python hits the single equal sign which we will call the assignment statement what it does it always goes to the right hand side first. So whenever and I mean whenever whenever you see a single equal sign always go to the right hand side in your mind and check what is there and totally ignore what is on the left hand side and only if the right hand side works without error will the left hand side be looked at by Python. So what happens? Python looks at the 42 and it of course understands what 42 means and then in memory and now note that I draw the memory diagram Python will create a box will write a 42 in there and yeah that's it. And then after this box is created what Python does now this box is created without an error it will go to the left hand side and see that okay I want to assign this box to the variable A so when it goes into another section in its memory where it stores all the names it knows about and it writes a name A and then it makes a reference the object and note how I accidentally used the correct word so as I drew the boxes here in my diagrams objects are boxes that's basically already telling you what an object is an object in Python is nothing but a box somewhere in memory that contains only zeros and ones and because we are not studying computer science here we don't really care about what the zeros and ones are in this box but what we do care about is what the zeros and ones in this box mean and in this case the zeros and ones in this box they mean the integer number 42 to us which is why I put the number 42 inside okay so far so good this diagram by the way is not yet complete even after this code cell we were completed over the next couple of slides so then Python goes ahead to the second line to the right hand side and it evaluates this and here Python notes the dot and it knows that with the dot we imply a decimal number so Python knows that and it goes ahead and it makes some bigger box here and we write in there 42.0 and then after the box has successfully been created it goes to the list of our names it writes the name either and then it references the box in the object and note how I drew this box bigger because the decimals even though the decimals are all zeros but because the decimals need to be stored somewhere Python potentially needs more space more ones and zeros to model this that's why the second box is larger than the first one and then let's go ahead to the last line and then I told you that whenever we hit the double quotes here that we basically model text data so what Python does here it creates an even bigger box let's do it like this I exaggerate a little bit of course and I write in there Python rocks and then we create the name C and the name C references this box so the box is of course even bigger because somehow we don't know what text is here but somehow text must need more ones and zeros than simple numbers right even though we don't yet know how text is really modeled in memory okay so now that's kind of like how the memory looks like and again just to reiterate these boxes that is what I mean by an object and these boxes are drawn for us by Python and Python does all the handling of the boxes for us which is why we don't have to really deal with a lot of this memory things ourselves but it's still the paradigm of object orientation that is at work here then we go on so every object has three properties and all three of them are important and we will go over all of them now and I just want to emphasize every object always has all three properties and that's a big idea here so the first property is every object has an identity well just by looking at the memory diagram I have three boxes so they are at three different places in memory at least in the way I drew them so that's what I mean by identity so the box that A references is another box than the box that B references and so on so just by the fact that I have several boxes each of them has its own identity right so just like we as humans have an identity and usually our identity is derived from our name from our birth name maybe we change the name but then we only have another name but we still have the same identity basically we're still the same person even though we may change a name later on in our lives so but the important fact is we have an identity and so do boxes and what is the identity of a box we can find out with the built-in ID function so I call the function ID it's just like calling the function print ID already exists, Python knows about it and I call the function with the parentheses to call operator and I pass the function the variable A so let's execute this and I get back this big number so this seems random it's important to understand that this number is both it is not random and B it has no meaning so it's just the fact that somewhere in memory namely exactly at the address that is symbolized by this big number that's where the object is so I think of objects like this the upper left hand corner that's the beginning of the object the lower right hand corner is the end of the object and the beginning of the object that's the address in memory and this is what we can find out with the ID function the ID function is really not important in Python at all I just want to point you to the fact that we could actually find out where in memory something is and of course this also holds true for B and C they also have identities and as we see they are placed somewhere else and even though we cannot interpret these numbers we could at least think that the numbers below they start with 1, 4, 0 and the number at the top starts with 9, 4, 3 so we could already, can already see that the objects are very far away in memory actually and the decision on where something is put in memory that is done by Python for us so why is identity important? Well identity is important because sometimes I want to compare two objects or I want to do something with two objects for example check if their value also a technical term is the same and I do this with the double equal operator so the double equal operator is the so-called comparison operator it looks at the left-hand side and the right-hand side and it checks if both of them have the same value that's important we're not checking here if the two objects of the left and right-hand side are indeed the same object so we don't check identity here but we do check value in other words the double equal sign does not check if two boxes are the same box it checks if two boxes contain the same contents same value so let's ask Python if A and B do indeed contain the same value and the answer is true so in other words Python looked at the 42 integer and it looked at the 42.0 float or decimal number and it said that those two numbers they are in fact the same however note that down here we have a dot zero in the box up here we don't have a dot zero but Python is still able to tell us that okay those two boxes they have the same contents and in this regard it is important to understand that equality here has something to do with how we humans think of the boxes so we humans we don't really care how you know how a number is stored if we just write 42 or if you write 42.0 for us humans it is the same however for a computer the 42.0 needs a lot more ones and zero so for a computer those two boxes they the contents they are definitely not the same however the meaning of the ones and zeros is the same for us humans and because of that the equality or comparison operator tells us yes that's what the true means on the contrary I can also ask Python if A and B have the same identity how do we do that I use another operator which is called the identity operator which is written out as the letters I and S so the word is so note how A is B if I execute this I get back false because why do I get false well A and B obviously the two variables A and B they point at different objects so the object A points to has a different identity than the object B points to which is why I see false so note how the double equals sign and the S word they syntactically they are basically the same thing they are both operators so before that in the intersection on arithmetic operators we saw the plus sign the minus sign and usually it was just one symbol but we also saw a double slash actually so most of the operators they consist of just one symbol but one symbol alone is not the definition of an operator so there are many many more operators than just individual symbols for example the word is and implementation wise in Python some people would actually disagree with me when I say is is an operator however in this course we will treat it as an operator so we will say that the double equal sign syntactically speaking so grammatically speaking is the same as the word is it's an operator that takes two operands binary operator okay so and of course maybe one thing to note here just in case if I mean obviously if I can ask the question if two different variables have the same identity then we can expect that it is actually possible to have several names to point at the same object because otherwise it wouldn't make any sense to have this operator in the first place and also if two variables reference the same object in memory then of course the value will always be the same right so in other words if a is b is true then a double equals b also must be true so a true here implies a true up here but the vice versa is not true so let's continue so that was the first big property that every object has which is the identity the second big property every object has is what we call its data type and note that I also refer to this as an object's behavior so we can ask the question do different kinds of different types of objects behave differently when we interact with them and the answer will be yes and the way an object behaves when we interact with it is basically governed by what type it is so let's see what are the three data types for the three objects that we have how do we do that? we call the built-in type function and I pass it the variable a so I call type of a and I get back int and int is short for integer and that is a data type and this type is basically a whole number that's what we would understand under a whole number that's what an integer is so how do we do that in the diagram? in the diagrams I usually put a little tag up here where I say this is an int an int object so let's check the data types of the other two objects for example b what's the type of b? it is float so decimal numbers they are represented in Python by objects of type float okay so now you may wonder why is that important so as I said different types of objects exhibit different behavior when we interact with them so for example the float object b I can ask hey b are you an integer? and then the answer is if I execute the set the answer is true and this makes sense because if we look at the box here that b points at it says 42.000 and so on so it's always o here so the 42 can be seen as an integer or in other words if we cut off all the decimals we would not lose any information here it would still be correct and so it makes sense that we are able to ask a float hey are you an integer or not and if we have a different number let's say 42.1 then this integer would return false here now regarding the syntax I'm also showing you a little bit of what is yet to come so b here is just the variable and then there is a dot and the dot here is also an operator and it's called unconvincingly the dot operator sometimes more formally it's called the attribute attribute access operator and then we write this integer and this integer is basically a function so it's just like type above or id or print it's a function and we see that because I also call it so I have opening and closing parentheses so I call the function is integer however the difference between the type function above and the integer function below is that the type function exists independent of any object it just exists in Corpisen we can always use the type function same for id same for print the integer function only exists for float objects in other words these functions or this function is what we will say is bound to the object b or to the object that the variable b references so and that's just a little technical term here and also functions that are bound to some object they have a different name sometimes formally they are also called a method so at the end of the day a method is also a function the only difference is that a method always belongs to some object and now you may wonder couldn't I ask int object 42 if it is an integer because you know we would expect that this works now that's you know a false friend here if we want to ask an integer if it's an integer we know the answer already the answer should be true intuitively speaking because a box of type int can only model integers so we know even before we look at the concrete value the contents in the box before we do that we already know that this must be an integer and because of that when I execute the next line of code next cell here I get an attribute error in other words python yells at me and says hey I know what a is but a doesn't know what is integer means and that's basically what the error message says and that's the first example of an error message that we see here and an error message always consists of two things so first we see the type of error which is here the attribute error and then usually error messages have some descriptive error message here sometimes they are you know not adding a lot of information so the word attribute error is the more important thing here but for a beginner this may be easier to read so in other words you know what python is telling us it says okay there is no attribute called is integer on the object that a references and that is also why the dot operator called the attribute access error because is integer is basically the attribute okay um so uh what do we take from this well what do we take from this is that um different types of objects have different methods on them for example the float uh object we can ask uh if it is an integer for the int object we cannot do that so let's look at our third example let's look at the object that c points to so let's first ask what is it and um and python tells me the type of c is uh str so let's write str here str is an abbreviation it stands for string and string is basically the default type uh the default data type that we use to model textual data and the word string is just an uh an old formal word which uh in more modern literature would be called sequence and um but string is the historical term for text strings and we will look at text strings in much detail uh in chapter six so um for now what we just look at what can we do with a str or string object that we cannot do with int and float objects well for example we can ask c to give us back a copy uh that is lower cased so python rocks the original string uh had an uppercase p and uh i could you know go ahead and and say c dot lower and then i get back a new text string uh where python rocks is all uh lower cased in the same way i can of course say dot upper and i get uppercase letters and these are functionalities behavior so to say that the numeric types don't have but the text type the string type has okay so now we understand that um the type determines how we can interact with an object so now the last of the three properties that every object has is what we will call a value or the object's value and what do we mean by value well we mean by value basically the contents of the box and the contents of the box they have a meaning we know that as i said earlier inside the box there are only ones and zeros and the ones and zeros they have no meaning so for a computer the ones and zeros never have a meaning because a computer at least to this day uh does not really you know have the conceptual reasoning power that we humans have at least not yet and that's why the zeros and ones inside the boxes they add zeros and ones to the computer but for us as humans the zeros and ones they mean something in particular they mean the number 42 in 42 a and b here and also the text python rocks and um so that's what i mean by semantic meaning this is what we humans understand of it so how can we check the value in python well very easy so if i have a variable that references an object i can get to the object's value by just evaluating that's a technical term by just evaluating the variable a if i execute yourself i get back 42 so this is python's way of telling me you know the contents of a are 42 note that the way in which python gives me back um the the the contents of the box is in a way that i can just copy paste back into a cell and if i execute a cell what happens is a new object would be created and given back to me so this is what we call a literal notation so if python if we can copy paste some output from python back into the console and python understands it then this is a literal notation because we can literally type it into the console and python understands it so python understands the symbols and then of course because at the end of the day everything that is output to us is only just pixels and ones and zeros for a computer so the computer has to like understand it in a different way and what is the difference between an integer and the and the float well the float has the dot symbol in it somewhere so if i copy paste the 42.0 back into the console python also understands it of course and now creates a new float object with the value 42 and this is also a literal literal because python does understand it and then lastly of course the value of c is just python rocks and here we have to see i also noted this earlier in the literal in the default literal notation of text strings python outputs the text strings within single quotes and in this book i will use double quotes when entering strings by default okay so now let's talk about uh something else let's talk about what are formal languages and how do they relate to uh natural languages so formal languages are languages that are made up that are designed basically and of course the programming language is a formal language but you also know other your other formal languages for example think of chemistry in chemistry water is symbolized by a sequence h2o so what does h2o stand for so h2o stands for um what um basically means that water is uh or any molecule of water is made up of two atoms of h the h atom and one um one atom of the old type so to say and they're put together and together they make up water i'm not a chemist expert so um i i cannot tell you a lot about this but even these languages have syntactic rules for example the the two in h2o it always belongs to the number uh to the letter that precedes it it does not belong to the letter that comes after it so the two belongs to the h not to the o and in other words we could write two h o this wouldn't make sense in chemistry in chemistry terms and so that's an example of some other formal language and programming languages are just formal languages and the big difference to natural languages is that uh natural languages they evolve naturally and they all have rules as well but uh the rules in natural languages they are not really strict so i'm for example a native german speaker and if you study german you will learn a lot about rules but you will learn um at least 10 times the number of exceptions of the rules then you will learn rules and this is probably true for most languages and in programming languages or formal languages you don't want to have exceptions so let's look at some of the rules and especially what happens when a rule is you know not followed and results in error so in the beginning for a programmer usually the most common error you will make will be a syntax error which means you type something into jubile notebook and python does not understand what you want whenever this happens this is most likely a syntax error so i'll give you some examples so let's say as business people we want to model let's say accounting software or finance software so we are seeing integers and floats now but let's say i want to add up numbers that for us in the application attend mean prices of something so let's say i want to add up two dollar prices what can i do well i write two float numbers here and i also add to them a dollar sign right so why would i want to do that well maybe in my accounting application that i'm going to write i also will have some euro prices and i don't want to mix up dollar and euro prices so maybe that's what my intention is however if i execute this code cell python doesn't understand it and the reason is the dollar symbol is an invalid symbol python just has no way to know it because it's just not defined and python is nice enough to also give us back an estimate of where it thinks you did the mistake so here we see that this is the code that we typed and there is a little arrow here and the arrow points at the dollar symbol so that's python's way of letting us know that it does not understand the dollar symbol so in other words if we want to model an accounting software we would have to use either integers or floats and then we would have to use maybe comments to tell our reader or tell ourselves in the code that we are working with dollar or euro prices or whatever but we cannot just make something up another way of a syntax error is for example here in the for loop where well what's wrong here actually let's see i execute this and well basically the end of the header line something is wrong and python gives me an error and it points here and it says invalid syntax but there is nothing and what's the problem here so the problem really is that i just forgot to type something here and what i forgot to type is a colon so if i type a colon here and execute again the code works and we see also that here that the for loop actually does indeed loop over the individual 12 numbers and print them out one by one on a line on their own but if i forget the colon then i do get a syntax error and that's a rule that is common in python so whenever you use syntax for example a for loop for statement that consists of a header line and some indented code block then it's not sufficient that you indent the code block by four spaces but you also have to end the header line before the code block with a colon otherwise it simply doesn't work okay let's go on um so what's wrong here i did not forget the colon so let's execute this and now python gives me indentation error an indentation error is a special kind of a syntax error and it basically tells me that the command print number is not correctly indented and the reason is of course that the for statement as we have seen now requires us to have at least one line of code in the code block that is indented so we want to execute code repeatedly for every element in this list of numbers and not just once so how can we fix this well we just add for example one space here run it again and it works however the convention is to not just use one space but to use four spaces and we see this in driven notebook because if i have like only one space the word print is in red if i have four spaces the word print turns green and this is driven notebooks way of letting me know that this is the the way it wants it okay so these are syntax errors and again syntax errors for us are nice even if as a beginner we might get frustrated because we see many of them in the beginning the syntax errors are nice because we will see them actually because as we will see in soon there are also errors that are actually very dangerous that we don't even see that they exist because we don't get an error message so syntax errors they're usually the easiest to fix another kind of error is what we would call a runtime error so a runtime error means that it's not the syntax that is wrong so it means around a runtime error occurs when python indeed understands what we want from it so it can execute the code however for some value and value being something inside some box it cannot do it cannot execute the code and there's typical example for that the typical example is division by zero so what should python do here we divide one by zero and as we know from high school dividing one by zero shouldn't work so let's check what python does python also raises an error here it's called the zero division error and then it gives us the super helpful message division by zero down here so sometimes the descriptive error message they are simply not really helpful so what's the problem here the problem is not the syntax so python understands we have a number the one we have another number the zero and we want to divide the first by the second so python understands everything but then it says well really i don't know how to divide by zero and what can we change well we could go ahead and just add a little bit to the zero and then somehow magically it works even though this is not a good example because if you divide by a very small number very close to zero then we get what is called so-called overflow error so then i mean we know that one divided by zero basically should go to infinity and that's what we see here so this is not really helpful either but at least it works and again if i change the value to zero then i get a zero zero division error so runtime errors they are characterized by the fact that the code sometimes works it works as long as the input to the code is good but once the code is to be run with invalid input then the the code doesn't work so that's a big difference to the syntax error right a syntax error never runs a runtime error means the code does run but in some edge cases it does not run and now we have a third kind of error which is called a semantic error and these are the most dangerous errors because that means code will definitely run there is no error message that we get however there's something wrong still so let's go to the introduction example again where we want to calculate the average of all even numbers in a list from one to twelve and let's execute this again and we see no result why because the last line of code is not an expression it's a statement so we assign some result to some variable and here we go ahead and let's read it out and now it's 3.5 so it's obviously wrong because we know that the result should be 7 so the question is now what is wrong here and if we look closely at the code we see that the error is here we misspelled or we basically use the wrong variable here we use the variable count which works because it exists however the correct version would have the variable number here so then it works so what kind of an error is this well this is an error where we can we only have to you know where we cannot blame the computer or anything else this is just a human coding error and there is a famous example of an of an error that is kind of similar to this in the early 2000s or late 90s NASA sent some drone to Mars and the drone was on its way for several years from Earth to Mars and once it reached the orbit of Mars it tried to land and what happened then was as it orbited Mars it got burned and NASA lost this device and then it was on the media and then they found out they did an analysis of what happened and then they found out that some engineered when they programmed the software to do the flight control they did not use meters per second for some speed but they used feet or something so they used the wrong unit as a count and so that is totally an error where you know we don't see it no one sees that this error exists the only way to find out about this error is if we take some test input data for which we can calculate the output by hand and for which we can then verify if our code runs correct or not and that's an example of a so-called semantic error because semantic error in the sense because there is something semantically wrong with the code it does not do what we wanted to do but the computer doesn't see it because the computer does exactly what we tell it to do it does the wrong computation so how can we prevent errors by following best practices so what are some best practices I would just briefly show how I would rewrite our introduction example with some more you know more advanced Python syntax and you don't have to understand everything here right now it's just to show you that there are best practices so let's start again we have our list the numbers the numbers that were given and then what we do is instead of looping which we did in the introduction example we create a new list called events and the new list is derived out of the existing list numbers and we see there is a four inside the brackets so there is a there is a loop going on here and this is an example of a so-called list comprehension and list comprehensions we will cover in detail in chapter seven so what this basically does is we look at the first list and this number is above and we create a new list out of it and what we do is we only keep the even numbers so we filter out the odd numbers that's what this does here so we look at the we divide every number we loop over all the numbers we buy the variable n and then we look if the n moderately divided by 2 has no rest and if it has no rest we know n must be an even number so we keep all the even numbers let's execute this cell and now we have an intermediate result which is a list called events which is a list that only consists of even numbers and now we can do something that yeah that is rather trivial we just calculated the sum of all the numbers in it and then we count how many elements are in the events and then we divide the sum by the count and we did that within the for loop by keeping track of two variables manually in a way and here we just use a so-called we use so-called built-in functions sum and lend they exist in Python they're built in and sum takes anything that we will soon identify to be a sequence and one type of a sequence is the list type so we can pass the list events to a sum and that sums up all the elements and then also we can pass the events list also to lend the the lend function and this of course stands for length and is another word for counting how many elements on this list and then we of course get the same result and why is this better well it's better for two reasons first we use built-in functions which means the code runs faster than the for loop that we wrote on our own and second we know that sum and length they work they are tested we know they are correct so that's always good if you write we the goal is always the best practice is to write as few lines of code as we can because with every line of code that we write to solve a problem there is one more line where we can actually make a bug and we don't want that so we want to code as few lines possible that's usually the goal and that's also something as a beginner that you have to fight right your instinct is you want to write lots of code because you like coding early on and you want to show yourself how good you are so you want to write many lines of code but the best practice is to have as few lines of code as possible and then this is one aspect so sum the built-in functions sum and then they are more performant they are correct and then there's a second aspect to all of this and i would argue that this way of writing the problem is more expressive so what do i mean by that well we start with a list numbers and then we express the idea that we take these numbers and we filter out the odd numbers and are left with another list that is consisting of only even numbers that's like the first step and then the average step is also very expressive in that we say well the average is just the sum of something divided by the count of something so we don't have to keep track of a running total this is a way easier to read and understand and so that's also a nice side benefit that we have here okay let's continue a little bit with some other example and we will introduce some more words some more technical terms in particular we will now look at the left-hand side of an assignment statement and we will analyze what are variables so i've used the term variables before and then there are also two other names called words called names and identifiers that are closely related and then there's also another term called references and yeah we will now look at how do these terms relate to each other and again as i said before in this course i will try to you know use technical terms with a very narrow and a dedicated meaning so a variable will be something different than a name and this also will be something different than a reference so let's continue with an example let's create a variable called variable and assign to it the float 20 let's execute this what happens in code what happens in code is some rather big box is created we write 20.0 in here we know by now that this is a float type so we put the type here and then we go that this is what happens on the right hand side in the memory and then on the left hand side where we have a list of all the names we know about python will go ahead and it will write a name called variables and then then we create this arrow that points from the name to the box and this is what happened in this line of code and now to introduce the technical terms the word variable here this is what we mean by name so there is it somewhere in python there is a list of our names that python knows about and we can change this list a little bit by for example the assignment statement so what we do here is we create a new name called variables and then this name points to some object in memory and this pointing this arrow here this is what we mean by a reference so this is the name the arrow is the reference and then both of them together this is what we mean variables what we mean with the term variable so a variable is always a name pointing somewhere and a name does not necessarily have to point somewhere we will see examples where a name in the list of names in python may not have a reference so we really I really want to emphasize the name and the reference are two different concepts although in most applications in most examples we will see them together all the time so let's go on variable is now 20.0 so let's go ahead and now assign to the variable a variable again now this time the integer 20 I execute this line of code and now the question is what happens in memory well what happens is this python creates a new box that is definitely smaller in the first box and writes the term 20 in there so this is the integer 20 and then we label the box with the int type and now the question is what happens python tries to set up a name variable that references this object so then python goes ahead and sees that there is already a reference there so what does python do well python goes ahead and removes the reference here and then creates a new reference to the new object and now you may wonder what happens to the float the float 20.0 the answer is we don't know we cannot tell python will in regular intervals execute something that we call garbage collection and what that means is python will in regular intervals go through the memory and check if there are any objects that has no reference to them and if it finds an object where there is no reference to it then it will remove them from the memory and clear up the memory so that other objects can use the new space the free space however this does not happen immediately so it could be that after we create the integer 20 that the float 20.0 will still float around in memory you know for some time however because we have no reference going to this float what we can do is we can pretend as if the float was removed right away because we cannot reconstruct it we have we will not have any way of creating or getting back to this object now let's continue with the code if i now execute the next cell the variable is now 20 and not 20.0 anymore in some programming languages this would not work and the reason why is because in some other programming languages the type of something the data type of something is attached to the variable in python this is not the case as we have seen in python the type of a variable is attached to the object itself here and because of that i can do what i could summarize as this i could say in this example that i created a variable with the float 20.0 and i changed the type of the variable to end however as we solve diagram in memory we know that this is just you know not correct because we did not really change the type of the variable we also did not change the type of the float object in fact we created a new object that just happens to have ones and zeros in it that mean the same as the ones and zeros in in another object that's all we did but we did create a new object and then we moved arrows we created a new reference and we removed an old reference but we never changed the type of anything so types they always belong to the to the object and any variable can in its lifetime reference objects of different type and that's something other programming languages many other programming languages cannot do and that's also something that i would not recommend you to do all the time so having a variable point to a different types of objects within the same code base is kind of like makes the code base harder to read and harder to understand it's possible as we see but it's not really recommended okay let's go ahead and do something with the 20 for example i execute next code cell which reads like this variable asterix equals four and now this asterix equal seems weird so whenever you see a single equal sign the assignment statement and we prepended with an operator like the asterix in this case what this really means is this really reads like what is here written as a comment it it reads like we set two variable whatever where variable was times four in other words the variable name on the left hand side will be inserted as the first operand on the right hand side that's just an abbreviation so this is shorter than this but it's exactly the same thing that that is happening and sometimes we call this to update a variable but we don't really update a variable we we will what we will see we will create a new object so let me let me execute this code cell and let's see what happens in memory well what happens is python follows the the name variables to the the object 20 and then multiplies it by four and 20 multiplied by four will give me 80 right so what python will do is it will create a new box and it will write 80 in it it's also an int and then python goes ahead and removes the reference and then python will reference the 80 and as we said because there is no more reference to the 20 we pretend as if the 20 is deleted right away okay so let's check if we calculate this correctly yes variable is no 80 and now we go ahead and we divide variable by two and then assign the result to variable again so we also use this a short form of the assignment operator sometimes these these assignment statements with a prefix of an operator they are also referred to as augmented assignment statements so let's execute this so what does it do so we follow variables again to the 80 and then we divide 80 by two and we use the double slash meaning we will get back another integer so 80 divided by two will give me a 40 so let's draw a new box 40 int and now this reference will go away we pretend as if the 80 is gone right away too and a new reference is created okay so that's how memory works and note how every time we execute one of these statements a new a new box a new object is created so um that is um yeah just something to know and then one last time we add two to it so what we do is we'll follow variables again to the 40 we add two to it which makes it um see this makes it 42 of course and it's also an int and then one last time this reference gets removed we pretend as if the object is gone and then a new reference is created which references the new 42 object and indeed the variable is 42 so this is what happens in memory okay so now um what we can do is we can of course um reference variable again it's 42 because I mean I didn't change anything here and then we can ask the question can we remove the reference without creating a new object so can we just delete the reference and of course we can do this um we do this with the del statement so by saying del variable what happens in memory is this uh python goes to the list of our names it knows about it checks if there is a name called variable it finds at the name variable and then it deletes the name variable and also at the same time it removes this reference so the reference is gone and then python sometime later runs its garbage collector and the garbage collector checks are there any objects that have no reference to them and then the garbage collector will find the 42 and will of course get rid of the 42 as well however the del statement is in my opinion um misnamed a little bit because we don't really delete uh as something here what we do here is we do reference I mean we could say that we delete something but we don't delete objects the only thing we delete really is the name right and by deleting the name we get rid of the reference and only if we remove the last reference to an object this objects get removed so please don't read the del variable statement here as we delete the the object that's not what's going on we only delete the name from the list of our names and then of course if we try to look up variable after that again python does not know about it and gives us a name error and that is why in previously I referred to this as names here and remember the the title of the last section here in this chapter was titled variables versus names versus identifiers versus references and one reason why I prefer to use the word names here and not identifiers is because in most of the error messages that python prints to us it uses the the word name and not identifier but the words names and name and identifier are usually considered synonyms so um yeah that's maybe also something to note but again as I said earlier we call this here the name the error we call the reference and together the two we call them variable the term the technical term identifier is not so important in this course okay so now comes a section that usually confuses people but I will show in a way with the diagrams so that you are not confused okay so let's go on I give you an example and the example goes like this we set the variable a to the object the integer object with the value 42 so what happens in memory well what happens in memory is this we create the 42 here for example here it's of course an integer and then we create the name a and make the name a reference 42 this is what happened and let's go on and execute the next line of code which says we set b to whatever a is pointing to so this next line does not mean that a and b are the same it means we will set b to reference the object that a currently references so what does that mean python goes into the the list of our names it looks up a it finds that here is this object 42 so this is what happens but when python evaluates the right hand side right it looks it just looks up the a it ends up here with the 42 and then once the right hand side is done evaluating python will take the object it has and will assign it to the variable b so we are here at the 42 so that means we create a new name called b and make this point to the same object that we currently evaluate so now we have a situation where we have two names referencing the same object in memory and let's go ahead in the code let's evaluate what is b well b is of course 42 that makes sense so let's go ahead and set a equal to 87 so what happens now python goes ahead and creates a new object with the 78 in there 87 and labels it within and now we want to set this object to the to the name a what python does is it recognizes that there is already a reference so it deletes this reference and then it creates a new reference to this and what we see in the diagram is that b is still referencing the 42 that's important so if i now go ahead and ask python hey what is a python tells me a a is 87 and then i asked python hey what is b it will tell me hey it's still 42 so some people are confused when they see the code here on the presentation because they say well aren't b and a supposed to be equal well yes they are equal but only in the in the moment when we set them equal to each other once we continue with execution down here a and b may certainly point to two different objects again and this is exactly what happened here okay and now comes the funny part so funny part is we do the same exercise again just with a list so here i create a list with the numbers one two three in it and i make i basically make a variable called x reference them so how do i create how do i draw lists in my memory diagrams well we haven't done this before so this is new so what python does is python goes to the right hand side and it evaluates the right hand side and it sees the brackets and that is the indication to python hey please create a list object and then python counts how many elements will be in the list and it will be three so python must reserve enough space to fit three elements inside however what python really does in memory is this it creates a thing that is very long and we will give it several so-called slots and these slots these are basic places where we can put something in and this makes sense because we are creating a list object so we want to store many many things inside the list object and these slots they are the same distance right that's important and also note python is well aware that we only want to put three elements inside but it creates many more slots how many it's not important it's usually a number that is well defined and it's usually higher than whatever we want to put inside and it differs it depends on how big of a list we want to create but the only thing that we for now need to understand is python creates this thing here with slots and such a thing which has the slots this is what in computer science literature is called an array and then python goes ahead and with the execution with the evaluation and it evaluates the one the first element and what it then does is it creates a new object with a one and puts in here and then it goes back into the the first slot and it makes a reference from the first slot to the one note how i use a european style one here this is not a seven for american people maybe i should in future use the american one with just a one mark from top to bottom but that's supposed to be a one and then what python does it it goes to the next element the second one and what it will do it will create a second object so let's say it creates an object with the value two in it an int object and you will make this point here this is how it works and then one last time it looks at the third element which is the number three so it will create another object and make a third reference and now the list is basically done and only now that the right hand side is totally evaluated will python go ahead and there was no error so now python will go ahead and will create a name called x and x will point at the beginning of the list that's it that's what lists look like in memory so now you may wonder what is the type of the of a list well unsurprisingly the type of a list object is just list so we may put a tag here and write list in it and now we have a list of three elements and now we do the same the same step as before we create a new variable called y and we make it also reference x so what what happens here python will evaluate the right hand side so it will follow the x and it will get to this object to the beginning of the list object and then evaluation of the right hand side is done and then it will take the reference to this object and will assign it to a new name called y so it will create a new name y and will basically make this point here as well okay so same as before and now we do the same as before just a little different first let's just check okay maybe i should execute everything in order so now y is a list one two three but the important thing to know is even though i have two variables x and y i only have one list in memory that's important so now what can we do with lists well lists are there to collect several elements inside one object so maybe we want to access the individual objects we have seen one way to do that that was with a for loop how we can loop over a list but there is another way to get to the individual elements in the list which we call indexing so indexing is done with the index operator which is brackets so we write x which is the reference to the to the list and then we write brackets opening brackets and closing brackets and this is the so-called indexing operator and in the indexing operator we have to provide a whole number and integer because indexes that's basically they are they're just whole numbers and now there is one thing that you need to understand and this is not rocket science in python we start counting at zero so the first element here the one will get an index of zero maybe i can write an index here then maybe i have an index of one here maybe i have an index of two here so these are the indices and so if i want to access the first element how do i do that i tell python hey please go to the list to the list object called x and give me the first element so let's execute this and i get back the number one which is exactly this one here that's indexing some other languages like r for example but also i think julia they start to count at one some languages start to count at zero it really depends it's really not a big of a difference but you have to know because otherwise you will make off by one errors when you index and then of course what can we do with that well we can use the indexing operator on the left hand side of an assignment statement as well so here what i do is i create a new number called with the value 99 and i will assign this to the first slot in the list x let's execute this now what what happens in memory well we evaluate the right hand side first and this basically creates a new object 99 it's also of type int and then python will go ahead and say well now that i have the 99 let's make the reference the first reference in the x-less reference it so what will happen is the old reference is deleted and the new reference is created and now because there is no further reference to the one here we can pretend that the garbage collector just removes it and now the tricky part is if i now ask x what is x i get back a list with the 99 in the first element but also if i ask python hey what is y i also get back a 99 but now i cannot really surprise you at this time because i true the the diagram in memory but if i did not if i did not true draw this diagram and if you were just given you know this code here most students most beginners will expect that this 99 here in the first element of why now remains to be one and they are confused that this also 99 but with a memory diagram we are basically we are not in a position where we can get confused at all because we know to begin with that we only have one list object which just happens to have two names like a real name and a nickname so to say and just by changing something while one one name does not mean that we don't see the change why the other name in fact we do see it so that's why we see it here okay that's it and that was a bit tougher example but i think also quite easy and now let's get back and close up this chapter by coming back to a question that i raised in the beginning so in the beginning when we looked at what is considered output in jupyter notebook especially i told you that only the last expression in a code cell is given back to us as output so what does that mean that's i will give you an example so if i go back in memory to to this situation which is still the current situation in memory if i evaluate what is a i get back an 87 why because before that i made a point to an object with the value 87 that's an expression so why is that an expression well because i don't change anything i don't instruct python to make any permanent changes in memory and that's exactly what is the definition is it a rather you know it's a bit of an abstract thing here but it's actually not so hard so an expression is any is anything any combination of a variable with an operator with a literal that does something that gives me back some value that evaluates to something but does not have permanent side effects that's an important part of the definition so when i just read out the variable a python goes and looks up the the variable a it will follow the the reference to the 87 and then in a way that this is how sometimes i like to draw things it takes the 87 and i draw this in red here and it gives it back to us because we are asking for it right so that's what python does here this is why here in red as well um python gives us back the 87 because why well i asked for it i say python please evaluate this expression and python evaluates the a by looking it up by following it to the 87 and then finally giving it back to us so we say that the variable a evaluates to 87 that's what we would say and that's what we get back now an expression that can also be a literal so if i just type 42 and execute this i also get back 42 this is almost trivial without a memory diagram i wouldn't even know if how i could present this in a presentation here because uh this is so trivial if i say python hey python here is 42 and it gives back to me the 42 so what what's going on here why is this why do i put so much emphasis on this well what happens is um when i type 42 what python does is it reads the 42 and that's what we mean by evaluating it evaluates the 42 but i typed in and this leads to a new 42 object being created which is also of type int and then the evaluation is done so the object is here and whenever the evaluation is done the last object that was um um you know retrieved in the evaluation process is just given back to me as the user as the one that asked for it that's why i see the 42 here and then what happens is because i don't store away the 42 because you know i'm giving the 42 back and then i'm not putting a reference back to the 42 because of that the 42 is basically immediately forgotten um and then of course this we can also now cross out so this is what just happened and if i go ahead and i uh run the cell again now not now there's no now it says 92 in it if i run the cell with the um literal 42 in it one more time it says 93 so what happens is python goes ahead it reads it creates a new object which has the 42 in it again it uh labels it with int and then it gives it back to me like this i see it as the output and because i don't start away it's immediately forgotten at least i have to assume it is immediately forgotten so this is how we should think of what happens in memory right this is just a side note python has some optimization going on so especially for small numbers this is not what actually happens in memory so small numbers like 42 and 87 they only exist in memory once and we always get back the same number but i want to teach you a mental model here of how you should think of you know what the evaluation process is and how objects behave in general when they're not somehow optimized by python and this is how we should think of it so whenever we say we evaluate something or python evaluates something it basically means we do something in memory and maybe along the way new objects are created just like the 242s here and then the last object of the overall expression is just given back to me which i indicate with the red arrows i will usually not draw the red arrows because you know it's just too too much to draw and it's also trivial but after this last object is given back to me and i don't do anything with it i don't store it then i can assume that this object is immediately forgotten if of course not some other references going there which was the case for the 87 so let's go on so let's write another expression i said an expression is anything that consists of variables literals or meaning numbers and operators so connect by operators so here i have a variable minus the 42 so i have a variable i have an operator and i have the literal so i execute the cell i get back 45 so what happens here well what happens is python goes ahead it follows the a to the 87 and then it also goes ahead that's the the left hand side of the operator and then it evaluates the right hand side of the operator and the right hand side of the operator immediately creates a 42 and then python somehow looks at the 87 and the 42 and it knows it has to subtract one from the other so the subtraction is done and the subtraction leads to a new object with the value of 42 because that's the result and then the result is what is actually returned to me and that's what i see as the output and then of course the intermediate result the 42 but i had to create in memory here this gets actually removed because it was never never referenced by anything and then of course because i don't store away the reference to the 42 the 42 object also gets removed here however the 87 object because it still has the a reference here does not get removed so this is what happens in memory every time we execute one of these cells so when i said that an expression is any any code that does not have a permanent side effect in memory i did not mean that there is no side effect at all in memory in fact we see side effects the thing is the side effects that we see in memory they are basically forgotten because if we don't if we don't store away to retrieve this result then how should python you know keep back of it you know why should it keep back of it it's an intermediate thing it's for immediately forgotten that's how it works and of course one more example here if i have a minus 42 i can also divide it with integer division by nine i get back five and this is to illustrate that the definition of what what is an expression is also recursive so a is an expression 42 is an expression but also the a and the 42 as operands to the a minus operator is an expression and then also if we use this expression here and we put it in parentheses and we continue to calculate with it divided by nine the entire thing is also an expression and in this context we would probably call this here a sub expression because this expression is evaluated first and then the result of this the 40 the 45 object is divided by the nine and this results in a new object of five and then after the five is returned everything is basically forgotten everything except the a so this is how evaluation works in memory and usually the subtleties are not so important to know but i want to emphasize them here in this chapter early on so that you know when i speak of an expression what do i mean by the expression this is what i mean is i mean something it happens and it does you know something happens in memory and it does not have a permanent side effect so but what if there is a permanent side effect or let me ask the question in a in another way what is a perfect what is a permanent side effect in memory well this is what we would understand or this is what we would call a so-called statement so statements is a more generic thing here it's more generic than the expression so we have seen statements before for example most notably the assignment statement so here the 42 on the right hand side that's an expression so a new 42 object is created that this is what we mean by evaluating the 42 so 42 gets evaluated to some object and then the reference to this object is assigned to a so what this means is here currently in my memory diagram the a points to 87 and after executing the code cell that we have here what happens is let me see do we have space maybe here a new 42 object is created one more time and then because the a references to 87 this reference is now removed and because we have no further reference to the 87 we can pretend that the 87 is gone as well and then a new reference is put here to the a and this references the 42 and now note that because I have this arrow here I have a permanent side effect so before I executed the cell a was pointing to 87 and after executing your cell a is pointing at 42 so that is a permanent side effect and whenever we have a permanent side effect this means we don't have an expression and and most of the time this basically constitutes what what is called a statement in this case the assignment statement is called statement because it is a statement so that's a grammatical subtlety here in the beginning it's not so important that you understand all of the more abstract ideas here but I just want to raise a certain amount of awareness that you know that there are such concepts and then of course another statement that we've also seen before is the del statement to dereference a variable so by saying del a what happens is the the name a gets removed from the list of all names and the reference to the 42 also gets removed and because there is no further reference the 42 is forgotten okay so and that means because we deleted the name a we also have a permanent side effect right the name a was there before now it's not there anymore so this is a permanent side effect okay and lastly to finish today's chapter I want to just quickly talk about comments so we've seen comments in the introduction example in the beginning where we basically wrote what some piece of code does so usually how we use comments is like this well first what is a comment a comment is anything that begins with a pound sign or a what we would also call a hashtag and the convention is that if we start a comment at the end of a line we only we use two spaces here before the hashtag and one space after and then we write something in the in the comment and sometimes that's one way of writing a comment at the end of a line to refer to the line as such so here what we do is we say we have a distance and we have time and we say how are they measured they're measured in meters and seconds and then sometimes we use comments in a longer version and then we put them on a line on their own and for example here calculate the speed in kilometers per hour and we would also have a hashtag here and we would also describe this code so let's run this code and nothing fancy here but this is just the rule for hashtags or for comments and then of course how should you use comments well you should use comments to put information in your code that helps you yourself in the future to understand what you want to do with some you know certain code and for example here I calculate seconds I calculate 60 times 60 times 24 times 365 and obviously this is the number of seconds in the year and so I call the variable seconds but then I put a comment here that this means seconds in year and this comment this comment here is kind of useless I think it's you know overdone there's a better way to do this in this situation maybe just rename the variable to seconds per year and then you don't need a comment so the the rule for comments is this don't use too many comments but also don't use too few comments use comments may need to write down why you are doing something or what you're doing what in terms of what are you doing conceptually so in this case here I write I calculate the speed in kilometers I could also write convert something from I don't know miles per second to kilometer or whatever something like this I can write in the comment I should not put a comment here but says calculate the speed well because I can read it on my own that I'm calculating speed so the comment has to kind of make sense and yeah I would always recommend in the beginning to do you to start using comments from the beginning on so that a day from now you can also still understand what you actually meant when you wrote a piece of software okay so this concludes this first chapter so I hope you learned a lot this chapter again was rather high level so we will look at many many details in the next couple of chapters and yeah so it's not necessary that you really understand everything in this chapter in much detail but you should get a