{"id":2199,"date":"2011-07-17T18:12:27","date_gmt":"2011-07-17T18:12:27","guid":{"rendered":"http:\/\/cemclinux1.math.uwaterloo.ca\/~cscircles\/wordpress\/?page_id=2199"},"modified":"2011-07-17T18:12:27","modified_gmt":"2011-07-17T18:12:27","slug":"17-is","status":"publish","type":"page","link":"https:\/\/olescs.hkmu.edu.hk\/python\/17-is\/","title":{"rendered":"17: Is"},"content":{"rendered":"<!-- Please retain this notice and add more notes if you create a new version.<br \/>\nOriginal lesson author: David Pritchard, daveagp@gmail.com, http:\/\/cscircles.ca<br \/>\nLicense: http:\/\/creativecommons.org\/licenses\/by-nc-sa\/3.0\/-->\n<p>In this lesson, we give more detail about how Python stores lists. Copying and comparing lists can have unexpected consequences. We will explain how Python works internally, so that you can understand and avoid these mistakes. The general issue is that several different variables can \"point to\" or \"refer to\" the same list. Towards the end of the lesson we describe the \"<code>is<\/code>\" operator which tells whether two variables <em>really<\/em> point to exactly the same list.<\/p>\n<h1>Example<\/h1>\n<p>Let's say we want a code fragment to convert a list of lengths in inches called <code>oldSize<\/code>, to a list of the same lengths in centimeters called <code>newSize<\/code>. One way we might try\u00a0to do this is to use the line <code>newSize = oldSize<\/code>\u00a0to make a copy, and then go through and change all the values:<\/p>\n<pre>oldSize = [\"letter\", 8.5, 11] \u00a0 # size of paper in inches\nnewSize =\u00a0oldSize \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 # make a copy?\nnewSize[1] = newSize[1]*2.54 \u00a0 \u00a0# convert to cm\nnewSize[2] = newSize[2]*2.54 \u00a0 \u00a0# convert to cm<\/pre>Now let's see if this actually works. If you print <code>newSize<\/code> then it gives <code>[\"letter\", 21.59, 27.94]<\/code> as expected. What is important to notice is that when we print\u00a0<code>oldSize<\/code>, the values of <code>oldSize<\/code> have changed! We illustrate below:<\/p>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform0\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox0'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div>The second line of output is not what we expect!<div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 162px;'><textarea wrap='off' name='usercode0' id='usercode0'  cols=10 rows=6 readonly='readonly'  style = 'height : 162px;'  class='pyboxCode RO'>\noldSize = [\"letter\", 8.5, 11]   # size of paper in inches\nnewSize = oldSize               # make a copy?\nnewSize[1] = newSize[1]*2.54    # convert to cm\nnewSize[2] = newSize[2]*2.54    # convert to cm\nprint(newSize)                  # as expected, prints [\"letter\", 21.59, 27.94]\nprint(oldSize)                  # no longer holds [\"letter\", 8.5, 11]...<\/textarea><\/div>\n<div id='pbhistory0' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit0' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(0)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(0,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse0\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"0\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"494a411afbf4e7d2f944e2fdac6f0d61\"\/>\n<div id='pbresults0' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit0\").value = \"Run program\";document.getElementById(\"inputInUse0\").value = \"N\";<\/script>\n<\/p>\n<p>We will now give a detailed explanation of exactly what happened, using diagrams. The main problem is that <code>newSize = oldSize<\/code> didn't really copy the whole list: it just copied a <em>reference<\/em>\u00a0(arrow) to the same list.<\/p>\n<p><em>Click on the slide titles to change tabs.<\/em><\/p>\n<div class=\"accordion\"><br \/>\n<div class='collapseContain showing'>\n<div class='collapseHead'><span class='icon'><\/span>\nMemory\n<\/div>\n<div class='collapseBody'>We'll use a table to represent the variables and values in Python's memory. For example, after running the code<\/p>\n<pre>city = \"Moose Factory\"\npopulation = 2458\nemployer = city<\/pre>this table (with the black border) shows what Python's memory looks like:<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"..\/wp-content\/lesson_files\/img\/17\/slide1.png\" alt=\"\" width=\"480\" height=\"168\" \/><br\/>The first variable's name is <code>city<\/code> and its value is the string <code>\"Moose Factory\"<\/code>. The second variable's name is <code>population<\/code> and its value is the integer <code>2458<\/code>. The third variable's name is <code>employer<\/code> and its value is the string <code>\"Moose Factory\"<\/code>.<\/div><\/div><div class='collapseContain hiding'>\n<div class='collapseHead'><span class='icon'><\/span>\nLists in memory\n<\/div>\n<div class='collapseBody'>Next, we show what a <em>list<\/em> looks like in memory. For example, take the code fragment<\/p>\n<pre>myList = [\"Moose Factory\", 2458]<\/pre>This will just create one variable, named <code>myList<\/code>. A list is created, and the value of <code>myList<\/code> is set equal to \"point\" or \"refer\" to that list. We represent the list using a box, and the values of the list's entries are shown inside the box next to their corresponding indices. The list is shown in blue.<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"..\/wp-content\/lesson_files\/img\/17\/slide2.png\" alt=\"\" width=\"702\" height=\"168\" \/><br\/>The arrow shows that <code>myList<\/code> refers to this new list. The element at index 0 of the list is the string <code>\"Moose Factory\"<\/code>, and the element at index 1 is the integer <code>2458<\/code>. For example, if you <code>print(myList[1])<\/code> then Python will output <code>2458<\/code>.<\/div><\/div><div class='collapseContain hiding'>\n<div class='collapseHead'><span class='icon'><\/span>\nReplacing a list value\n<\/div>\n<div class='collapseBody'>Now we add one more line to the previous example, just for illustrative purposes. A baby is born, so we run the code fragment<\/p>\n<pre>myList = [\"Moose Factory\", 2458]\nmyList[1] = myList[1]+1<\/pre>Python calculates <code>2458+1<\/code> which equals <code>2459<\/code>, and this replaces the value at index 1 of the list. After the update, we have the diagram shown below.<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"..\/wp-content\/lesson_files\/img\/17\/slide3.png\" alt=\"\" width=\"702\" height=\"168\" \/><br\/>(The crossed-out\u00a0<span style=\"text-decoration: line-through\">2458<\/span>\u00a0is shown just to emphasize the change.)<\/div><\/div><div class='collapseContain hiding'>\n<div class='collapseHead'><span class='icon'><\/span>\n<code>oldSize<\/code> and <code>newSize<\/code>\n<\/div>\n<div class='collapseBody'>Now we get back to the main example. The first line was<\/p>\n<pre>oldSize = [\"letter\", 8.5, 11]<\/pre>and so Python's memory looks like the diagram below after this line is executed. We created a list of length 3.<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"..\/wp-content\/lesson_files\/img\/17\/slide4.png\" alt=\"\" width=\"702\" height=\"168\" \/><\/div><\/div><div class='collapseContain hiding'>\n<div class='collapseHead'><span class='icon'><\/span>\nMain problem\n<\/div>\n<div class='collapseBody'>In our program, the second line is<\/p>\n<pre>newSize = oldSize<\/pre>and the most important point in the lesson is here:\u00a0<strong><code>=<\/code> does not duplicate the list!<\/strong> Instead, it just creates\u00a0a new reference to the <strong>same<\/strong> list. This is illustrated by two different arrows pointing to the exact <strong>same<\/strong> box.<img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"..\/wp-content\/lesson_files\/img\/17\/slide5.png\" alt=\"\" width=\"702\" height=\"168\" \/><br\/>As the diagram shows, we have two variables, which both refer to the same list.<\/div><\/div><div class='collapseContain hiding'>\n<div class='collapseHead'><span class='icon'><\/span>\nUpdating\n<\/div>\n<div class='collapseBody'>Next, when the program reaches the line<\/p>\n<pre>newSize[1] = newSize[1]*2.54<\/pre>Python looks at <code>newSize<\/code>, looks up the value of its index 1 (8.5) and multiplies it by 2.54, and then replaces the value, as shown. However, since <code>oldSize<\/code> referred to the same list, a side effect is that we also affected what\u00a0<code>oldSize<\/code>\u00a0refers to!<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"..\/wp-content\/lesson_files\/img\/17\/slide6.png\" alt=\"\" width=\"702\" height=\"168\" \/><br\/>(Again <span style=\"text-decoration: line-through\">8.5<\/span>\u00a0is shown just to emphasize the change.)<\/div><\/div><div class='collapseContain hiding'>\n<div class='collapseHead'><span class='icon'><\/span>\nResult\n<\/div>\n<div class='collapseBody'>The next line is similar,<\/p>\n<pre>newSize[2] = newSize[2]*2.54<\/pre>which affects the other value in the list. After this line executes, Python's memory looks like the diagram shown below.<br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"..\/wp-content\/lesson_files\/img\/17\/slide7.png\" alt=\"\" width=\"702\" height=\"168\" \/><br\/>Now when we print either <code>newSize<\/code> <strong>or<\/strong> <code>oldSize<\/code>, Python outputs <code>[\"letter\", 21.59, 27.94]<\/code>.<\/div><\/div><\/div><br \/>\n<table class='pywarn'><tr><td class='pywarnleft'><img src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/files\/warning.png'\/><\/td><td class='pywarnright'><span> To just see the pictures without the commentary, <a href=\"http:\/\/cscircles.cemc.uwaterloo.ca\/visualize\/#code=oldSize%20%3D%20%5B%22letter%22%2C%208.5%2C%2011%5D%20%20%20%23%20size%20of%20paper%20in%20inches%0AnewSize%20%3D%20oldSize%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20make%20a%20copy%0AnewSize%5B1%5D%20%3D%20newSize%5B1%5D*2.54%20%20%20%20%23%20convert%20to%20cm%0AnewSize%5B2%5D%20%3D%20newSize%5B2%5D*2.54%20%20%20%20%23%20convert%20to%20cm%0Aprint(newSize)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20as%20expected%2C%20prints%20%5B%22letter%22%2C%2021.59%2C%2027.94%5D%0Aprint(oldSize)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20surprise!%20DOES%20NOT%20print%20%5B%22letter%22%2C%208.5%2C%2011%5D\">run the same code in the visualizer<\/a>. <\/span><\/td><\/table><\/p>\n<p><table class='pywarn'><tr><td class='pywarnleft'><img src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/files\/warning.png'\/><\/td><td class='pywarnright'><span> Actually,\u00a0<em>every<\/em>\u00a0value in Python is an object\u00a0living in a specific chunk of memory, and\u00a0<em>every<\/em> variable is just a reference\/pointer\/arrow.\u00a0E.g., in the first slide, memory only really contains one \"Moose Factory\" with two arrows to it.\u00a0Because number and string objects are \"immutable\" we draw them without arrows in these lessons, but behind the scenes, Python treats all data uniformly. <a href=\"http:\/\/www.greenteapress.com\/thinkpython\/html\/thinkpython011.html\">Read\u00a0more here<\/a>. <\/span><\/td><\/table><\/p>\n<h1>\"Deep\"\u00a0Copying a List in Python<\/h1>\n<p>In the above example, we use <code>=<\/code> to create a second pointer\/reference\/arrow to an existing, list, which is usually called a \"shallow\" copy.\u00a0Although it is <a class=\"hintlink\"  id=\"hintlink1\">sometimes useful<\/a> to do this, here it is not what we wanted. Instead, we wanted to create\u00a0an entirely new copy of that list. How can this be done?<\/p>\n<p>We'll give three solutions. They are all pretty much equivalent, but each one will teach you a new fact about Python, so all three are worth reading.<\/p>\n<h2>Method 1, using <code>[:]<\/code><\/h2>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform2\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox2'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div>Copying with <code>[:]<\/code><div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 110px;'><textarea wrap='off' name='usercode2' id='usercode2'  cols=10 rows=4 readonly='readonly'  style = 'height : 110px;'  class='pyboxCode RO'>\noldList = [\"first\", \"second\", \"third\"]\nnewList = oldList[:]     # create a copy\noldList.reverse()\nprint(newList, oldList)<\/textarea><\/div>\n<div id='pbhistory2' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit2' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(2)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(2,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse2\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"2\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"44a8639fa1434f2e1845c09d1ee8298d\"\/>\n<div id='pbresults2' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit2\").value = \"Run program\";document.getElementById(\"inputInUse2\").value = \"N\";<\/script>\n<\/p>\n<p>Above, we demonstrate that <code>newList = oldList[:]<\/code> creates a real copy of the old list. Although this syntax looks strange, it is a relative of something we already saw. In the <a href=\"\/7a-strings\/\">string lesson<\/a>, we introduced a way of extracting a substring: <code>string[first:tail]<\/code> returns the substring starting with index <code>first<\/code> and ending with index <code>tail-1<\/code>. We mentioned it can also apply to create sublists of lists. In addition,<\/p>\n<ul>\n<li>if you omit <code>first<\/code>, then it takes the default value of <code>0<\/code>;<\/li>\n<li>if you omit <code>tail<\/code>, then it takes the default value of <code>len<\/code>\u00a0(the length of the list\/string).<\/li>\n<\/ul>\n<p>So what really happens is that <code>oldList[:]<\/code> is creating a new sublist, but containing all of the same data as the original list, so it is a new copy.<\/p>\n<h2>Method 2, using <code>copy.copy()<\/code><\/h2>\n<p>There is a module called <code>copy<\/code>, which contains several methods related to copying. The simplest one is <code>copy.copy(L)<\/code>: when you call this on a list <code>L<\/code>, the function returns a real copy of <code>L<\/code>.<\/p>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform3\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox3'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div>Copying with\u00a0<code>copy.copy<\/code><div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 136px;'><textarea wrap='off' name='usercode3' id='usercode3'  cols=10 rows=5 readonly='readonly'  style = 'height : 136px;'  class='pyboxCode RO'>\nimport copy\noldList = [\"first\", \"second\", \"third\"]\nnewList = copy.copy(oldList)     # create a copy\noldList.reverse()\nprint(newList, oldList)<\/textarea><\/div>\n<div id='pbhistory3' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit3' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(3)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(3,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse3\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"3\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"4910619f4f5f9cf25b6847df12d1c89b\"\/>\n<div id='pbresults3' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit3\").value = \"Run program\";document.getElementById(\"inputInUse3\").value = \"N\";<\/script>\n<\/p>\n<p>The <code>copy.copy()<\/code> function also works for other kinds of objects, but we won't discuss them here.<\/p>\n<h2>Method 3, using\u00a0<code>list()<\/code><\/h2>\n<p>The last way of making a real copy is using the list() function. Ordinarily, <code>list()<\/code> is used to convert data from other types to the <code>list<\/code> type. (For example <code>list(\"hello\")<\/code> <a href=\"https:\/\/olescs.hkmu.edu.hk\/python\/console\/?consolecode=L%20%3D%20list%28%27hello%27%29%0Aprint%28type%28L%29%29%0Aprint%28L%29%0Aprint%28L%5B0%5D%29%0Aprint%28type%28L%5B0%5D%29%29\" target=\"_blank\">converts<\/a> the string \"hello\" to a 5-element list, each element being one character.) But if you try to convert something that is already a list into a list, it just makes a copy.<\/p>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform4\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox4'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div>Copying with\u00a0<code>list()<\/code><div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 110px;'><textarea wrap='off' name='usercode4' id='usercode4'  cols=10 rows=4 readonly='readonly'  style = 'height : 110px;'  class='pyboxCode RO'>\noldList = [\"first\", \"second\", \"third\"]\nnewList = list(oldList)     # create a copy\noldList.reverse()\nprint(newList, oldList)<\/textarea><\/div>\n<div id='pbhistory4' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit4' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(4)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(4,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse4\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"4\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"78fd6910476b10454ad98d4378cf77b2\"\/>\n<div id='pbresults4' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit4\").value = \"Run program\";document.getElementById(\"inputInUse4\").value = \"N\";<\/script>\n<\/p>\n<h2>Lists as Arguments<\/h2>\n<p>Notice that because of the way that lists work, any function which accepts a list as an argument can actually change the contents of the list. (You saw this already in the <code><a href=\"\/14-methods\/\">replace<\/a><\/code> exercise.)<\/p>\n<p><div class='pybox modeNeutral' id='pybox5'>\n<img title='You have not yet completed this problem.' src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/files\/icon.png' class='pycheck'\/><div class=\"heading\"><span class='type'>Short Answer Exercise: <\/span><span class='title'>List Argument<\/span><\/div>What number is output by the following program? <\/p>\n<pre>def func(list):<br\/> \u00a0\u00a0 list[0] = list[0] + list[1]<br\/> \u00a0\u00a0 list[1] = list[1] + list[0]<br\/>data = [3, 4]<br\/>func(data)<br\/>print(data[0]*data[1])<\/pre><label for=\"pyShortAnswer5\">Your answer (enter a number): <\/label><input type=\"text\" onkeypress=\"{if (event.keyCode==13) pbShortCheck(5)}\" id=\"pyShortAnswer5\"><div class=\"pyboxbuttons\"><input type=\"hidden\" name=\"type\" value=\"number\"\/><input type=\"hidden\" name=\"correct\" value=\"77\"\/><input type=\"hidden\" name=\"slug\" value=\"17.reference\"\/><input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type='submit' style='margin:5px;' value='Check answer' onClick = 'pbShortCheck(5)'\/><\/div><div class=\"pbresults\" id=\"pyShortResults5\"><\/div><div class=\"epilogue\">Correct! Inside <code>func<\/code>, we change the element at index 0 to 7, and the element at index 1 to 7+4=11. So we print 7*11.<\/div><\/div>\n<h2>Comparing lists using <code>is<\/code><\/h2>\n<p>When are two list variables <code>L1<\/code> and <code>L2<\/code> equal? There are two different ways that we can interpret this question:<\/p>\n<ul>\n<li><em>Same Identity<\/em>: Are <code>L1<\/code> and <code>L2<\/code> pointing\/referring to the exact same list object?<\/li>\n<li><em>Same Values<\/em>:\u00a0Are the contents of list <code>L1<\/code> equal to the contents of list <code>L2<\/code>?<\/li>\n<\/ul>\n<p>It turns out that in Python, the standard equality operator <code>==<\/code> has the <em>Same Values<\/em> meaning, as the following example shows.<\/p>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform6\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox6'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div>The meaning of <code>==<\/code><div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 84px;'><textarea wrap='off' name='usercode6' id='usercode6'  cols=10 rows=3 readonly='readonly'  style = 'height : 84px;'  class='pyboxCode RO'>\nL1 = ['text', 11]\nL2 = L1[:]        # make a copy\nprint(L1 == L2)   # Same Values?<\/textarea><\/div>\n<div id='pbhistory6' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit6' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(6)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(6,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse6\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"6\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"14c5779912209a08ee35289f5365c74a\"\/>\n<div id='pbresults6' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit6\").value = \"Run program\";document.getElementById(\"inputInUse6\").value = \"N\";<\/script>\n<\/p>\n<p>To test for <em>Same Identity<\/em>, Python has the <code>is<\/code> operator. We use this operator the same way as <code>==<\/code>: the syntax<\/p>\n<p style=\"text-align: center\"><code>\u00ablist1\u00bb is\u00a0\u00ablist2\u00bb<\/code><\/p>\n<p>returns <code>True<\/code> if the lists refer to the same list, and <code>False<\/code>\u00a0if they refer to different lists (even if they have the same contents).<\/p>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform7\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox7'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div>The meaning of\u00a0<code>is<\/code><div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 162px;'><textarea wrap='off' name='usercode7' id='usercode7'  cols=10 rows=6 readonly='readonly'  style = 'height : 162px;'  class='pyboxCode RO'>\nL = ['text', 11]\nLAgain = L             # another reference to L\nprint(LAgain is L)     # Same Identity? Yes\nLCopy = L[:]           # make a copy\nprint(LCopy == LAgain) # Same Values?   Yes, both are ['text', 11]\nprint(LCopy is LAgain) # Same Identity? No: LAgain is L, but LCopy is not L<\/textarea><\/div>\n<div id='pbhistory7' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit7' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(7)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(7,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse7\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"7\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"9b852f7b5486e559e1a1d08b0086a52b\"\/>\n<div id='pbresults7' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit7\").value = \"Run program\";document.getElementById(\"inputInUse7\").value = \"N\";<\/script>\n<\/p>\n<p><div class='pybox modeNeutral' id='pybox8'>\n<img title='You have not yet completed this problem.' src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/files\/icon.png' class='pycheck'\/><div class=\"heading\"><span class='type'>Short Answer Exercise: <\/span><span class='title'>True Count<\/span><\/div>How many times does\u00a0<code>True<\/code>\u00a0show up in the output of this program? (Draw a diagram to help keep track.) <\/p>\n<pre>list1 = [9, 1, 1]<br\/>list3 = list(list1)<br\/>list2 = list1<br\/>list4 = list3[:]<br\/>list1[0] = 4<br\/>list5 = list1<br\/>print(list1 is list2, list2 is list3, list3 is list4, list4 is list5)<br\/>print(list1 == list2, list2 == list3, list3 == list4, list4 == list5)<\/pre><label for=\"pyShortAnswer8\">Your answer (enter a number): <\/label><input type=\"text\" onkeypress=\"{if (event.keyCode==13) pbShortCheck(8)}\" id=\"pyShortAnswer8\"><div class=\"pyboxbuttons\"><input type=\"hidden\" name=\"type\" value=\"number\"\/><input type=\"hidden\" name=\"correct\" value=\"3\"\/><input type=\"hidden\" name=\"slug\" value=\"17.is\"\/><input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type='submit' style='margin:5px;' value='Check answer' onClick = 'pbShortCheck(8)'\/><\/div><div class=\"pbresults\" id=\"pyShortResults8\"><\/div><div class=\"epilogue\">Correct! The output is\n<code>\nTrue False False False<\/code>\n\nTrue False True False<\/div><\/div>\n<p><table class='pywarn'><tr><td class='pywarnleft'><img src='https:\/\/olescs.hkmu.edu.hk\/python\/wp-content\/plugins\/pybox\/files\/warning.png'\/><\/td><td class='pywarnright'><span> You should not use\u00a0<code>is<\/code>\u00a0with strings or numbers because == already correctly tests equality, and the behaviour of\u00a0<code>is<\/code>\u00a0is <a href=\"https:\/\/olescs.hkmu.edu.hk\/python\/console\/?consolecode=%23%20why%20is%20%22is%22%20tricksy%20for%20strings%3F%0Aprint%28%22foo%22%20is%20%22foo%22%2C%20%22foo%22%20is%20%22fo%22%2B%22o%22%29%20%23%20both%20True%2C%20due%20to%20string%20interning%0Aprint%28%22e%22%2A32%20is%20%22ee%22%2A16%29%20%23%20False%2C%20long%20strings%20are%20not%20interned%0AA%20%3D%20%22foo%22%0AB%20%3D%20%22foofoo%22%0AA%20%2A%3D%202%0Aprint%28A%20%3D%3D%20B%2C%20A%20is%20B%29%20%23%20True%20False%3A%20%2A%3D%20does%20not%20re-intern%20a%20string%0A%0A%23%20why%20is%20%22is%22%20tricksy%20for%20numbers%3F%0Aprint%281%2B1%20is%202%29%20%23%20True%2C%20but%20this%20behaviour%20is%20only%20for%20small%20ints%0Aprint%2810%2A%2A3%20is%201000%29%20%23%20False%0Aprint%281.5%20is%201.5%2C%201.5%20is%200.5%2A3%29%20%23%20True%2C%20False%0Aprint%28float%28%27NaN%27%29%3D%3Dfloat%28%27NaN%27%29%2C%20float%28%27NaN%27%29%20is%20float%28%27NaN%27%29%29%20%23%20both%20False%0Ax%20%3D%20float%28%27NaN%27%29%0Aprint%28x%20is%20x%2C%20x%20%3D%3D%20x%29%20%23%20True%20False%3B%20one%20of%20few%20examples%20with%20%27is%27T%2C%20%3D%3DF%0Aprint%280.0%20is%200%2C%200.0%20%3D%3D%200%29%20%23%20False%20True%0A%0A%23also%2C%20%22is%22%20not%20same%20as%20compare%20id%28%29%20http%3A%2F%2Fcodepad.org%2FXb0TaKl9%0A%0A\" target=\"_blank\">hard to predict<\/a> on strings and numbers. <\/span><\/td><\/table><\/p>\n<h2>Nested lists<\/h2>\n<p>We have already given most of the important information, but there is one other common situation worth mentioning. As mentioned in the previous lesson, a <em>nested list<\/em> is a list within another list, for example<\/p>\n<p style=\"text-align: center\"><code>sample = [365.25, [\"first\", 5]]<\/code><\/p>\n<p><code><\/code>The <em>outer list,<\/em>\u00a0which is what <code>sample<\/code> refers to, has two elements; the element at index 0 is a float and the element at index 1 is the <em>inner list<\/em>. The inner list is <code>[\"first\", 5]<\/code>. (You can have more levels of nesting too.) Once you start using nested lists, keep in mind:<\/p>\n<ul>\n<li>Applying the three methods above to <code>sample<\/code> will copy the outer list, but not the inner list. So <code>copy(sample)[1] is sample[1]<\/code>, meaning the copy still has a reference to part of the original list. This probably was not what you wanted. If you want to make a real copy at all levels, use <code>copy.deepcopy()<\/code>.<\/li>\n<li>Testing nested lists with <code>==<\/code> is pretty intuitive: Python recursively calls <code>==<\/code> on each list element. For example <code>[[1, 2], 3]==[[1, 2], 3]<\/code> is <code>True<\/code>, and <code>[[1, 2], 3]==[1, 2, 3]<\/code> is <code>False<\/code> since the first elements are different (<code>[1, 2] != 1<\/code>).<\/li>\n<\/ul>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform9\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox9'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div><code>deepcopy<\/code> and recursive equality<div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 266px;'><textarea wrap='off' name='usercode9' id='usercode9'  cols=10 rows=10 readonly='readonly'  style = 'height : 266px;'  class='pyboxCode RO'>\nimport copy\nsample = [365.25, [\"first\", 5]]\nclone = copy.copy(sample)\nprint(sample, clone)\nprint(sample == clone, sample is clone)\nprint(sample[1] == clone[1], sample[1] is clone[1])\ndeepclone = copy.deepcopy(sample)\nprint(deepclone)\nprint(sample == deepclone, sample is deepclone)\nprint(sample[1] == deepclone[1], sample[1] is deepclone[1])<\/textarea><\/div>\n<div id='pbhistory9' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit9' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(9)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(9,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse9\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"9\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"9e283f578fffcb8094b88d7e64992baa\"\/>\n<div id='pbresults9' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit9\").value = \"Run program\";document.getElementById(\"inputInUse9\").value = \"N\";<\/script>\n<\/p>\n<p>You have now completed this lesson! The following extra material is optional.<\/p>\n<hr \/>\n<h2>Tuples: <code>(\"immutable\", \"lists\")<\/code><\/h2>\n<p>We mentioned above that when you call a function on a list, it can alter the list. Sometimes you want to make this impossible! A solution in Python is to create <em>tuples<\/em>,\u00a0which are the same as lists except they can never be changed. We say lists are <em>\"mutable\"<\/em> and tuples are <em>\"immutable\"<\/em>. (Strings and numbers are also immutable.) This can be a useful way to prevent any programming errors from altering lists that should stay unchanged. Tuples are almost identical to lists except that they use round parentheses <code>()<\/code> instead of square brackets <code>[]<\/code>. You can convert between tuples and lists using <code>tuple()<\/code> and <code>list()<\/code>.<\/p>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform10\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox10'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div>Tubular tuples<div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 188px;'><textarea wrap='off' name='usercode10' id='usercode10'  cols=10 rows=7 readonly='readonly'  style = 'height : 188px;'  class='pyboxCode RO'>\nT = (3, 4, 5)\nprint(T)\nprint(type(T))           # tuple\nprint(T[0])              # the first item in the tuple\nprint(list(T))           # converting a tuple to a list\nprint(tuple([1, 2, 3]))  # converting a list to a tuple\nT[0] = \"three\"           # Error! You can't change tuple values<\/textarea><\/div>\n<div id='pbhistory10' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit10' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(10)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(10,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse10\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"10\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"7f077bc933194d6bbab91e4d6feb3a5a\"\/>\n<div id='pbresults10' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit10\").value = \"Run program\";document.getElementById(\"inputInUse10\").value = \"N\";<\/script>\n<\/p>\n<h2>To <code>\u221e<\/code> and Beyond: Self-Containment<\/h2>\n<p>It is possible to have a list that contains itself! Simply make a list, and then redirect one of its elements to point back to the whole list:<\/p>\n<p><form class=\"pbform\" action=\"#\" id=\"pbform11\" method=\"POST\">\n<div class='pybox modeNeutral  facultative' id='pybox11'>\n<div class=\"heading\"><span class=\"title\">Example<\/span><\/div>A circular reference<div class='pyboxTextwrap pyboxCodewrap RO '  style='height: 136px;'><textarea wrap='off' name='usercode11' id='usercode11'  cols=10 rows=5 readonly='readonly'  style = 'height : 136px;'  class='pyboxCode RO'>\nL = [\"zero\", \"one\"]\nL[1] = L\nprint(len(L))\nprint(L)\nprint(L is L[1])<\/textarea><\/div>\n<div id='pbhistory11' class='flexcontain' style='display:none;'><\/div>\n<div class='pyboxbuttons'><table><tr>\n<td><input type='submit' name='submit' id='submit11' value=' '\/><\/td>\n<td><input type='button' name='consolecopy' value=\"Open in console\" onclick=\"pbConsoleCopy(11)\" ><\/td>\n<td><input type='button' name='visualize' value=\"Visualize\" onclick=\"pbVisualize(11,'N')\" ><\/td>\n<\/tr><\/table><\/div>\n<input type=\"hidden\" name=\"lang\" value=\"en-US\"\/><input type=\"hidden\" id=\"inputInUse11\" name=\"inputInUse\" value=\"Y\"\/>\n<input type=\"hidden\" name=\"pyId\" value=\"11\"\/>\n<input type=\"hidden\" name=\"hash\" value=\"ef2417b9b7c2f2b395ad4f54e60f4005\"\/>\n<div id='pbresults11' class='pbresults'><\/div>\n<\/div>\n<\/form>\n<script type='text\/javascript'>document.getElementById(\"submit11\").value = \"Run program\";document.getElementById(\"inputInUse11\").value = \"N\";<\/script>\n<\/p>\n<p>Notice that Python's output engine is smart enough to recognize that the list loops back on itself: it prints \"<code>...<\/code>\" instead of printing all of <code>L<\/code> again, to avoid an infinite loop.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this lesson, we give more detail about how Python stores lists. Copying and comparing lists can have unexpected consequences. We will explain how Python works internally, so that you can understand and avoid these mistakes. The general issue is &hellip; <a href=\"https:\/\/olescs.hkmu.edu.hk\/python\/17-is\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-2199","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/pages\/2199"}],"collection":[{"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/comments?post=2199"}],"version-history":[{"count":0,"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/pages\/2199\/revisions"}],"wp:attachment":[{"href":"https:\/\/olescs.hkmu.edu.hk\/python\/wp-json\/wp\/v2\/media?parent=2199"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}