{"id":192,"date":"2021-12-31T16:21:33","date_gmt":"2021-12-31T16:21:33","guid":{"rendered":"http:\/\/juthon.com\/?p=192"},"modified":"2021-12-31T16:21:33","modified_gmt":"2021-12-31T16:21:33","slug":"passage-10-for-loop-part-ii","status":"publish","type":"post","link":"http:\/\/juthon.com\/index.php\/2021\/12\/31\/passage-10-for-loop-part-ii\/","title":{"rendered":"Passage 10:  for Loop (part&nbsp;II)"},"content":{"rendered":"\n<p>In this passage, we're continuing to learn the most popular loop in Python: the for&nbsp;loop.<\/p>\n\n\n\n<p>The for loop tells the program to perform an action multiple times with a single command.<\/p>\n\n\n\n<p>The first challenge that we face when we want to use this loop is to determine the number of repeti\u00adtions in the loop. Usually, this amount is self-imposed. All right: sometimes we need to arbitrarily decide how many times the loop should run through the loop, but more often we just want to iterate through <strong>all<\/strong> the items in the collection.<\/p>\n\n\n\n<p>Let's consider an example. On the basis of the list of first names \u2013 written with a lower case letter \u2013 we&nbsp;want to create a new list, rewriting each name with the first letter replaced with a capital letter:<\/p>\n\n\n\n<p>['ava', 'amelia', 'alexander', 'aiden', 'avery', 'abigail', 'asher', 'anthony', 'aria', 'andrew', 'adrian', 'aurora', 'angel', 'aaron', 'axel', 'addison', 'austin', 'aubrey', 'adam', 'audrey', 'aaliyah', 'anna', 'alice', 'amir', 'allison', 'ariana', 'autumn', 'ayden', 'ashton', 'august', 'adeline', 'adriel', 'athena', 'archer', 'adalynn', 'arthur', 'alex']<\/p>\n\n\n\n<p>So how many of these names are there in the collection? Will we count manually? Or (what might be easier) \u2013 will we use predefined functions to count elements in the collection<a href=\"#_ftn1\">[1]<\/a>? Or maybe\u2026 we will not be counting at&nbsp;all?<\/p>\n\n\n\n<p>Foreach loop<\/p>\n\n\n\n<p>The answer to the last question is: if we want to iterate over all the elements of the collection, recounting the elements is \u2014 from a human perspective \u2014 completely unnecessary work. Unfortunately, from the computer perspective it is different. The computer does not have the ability to look in a panoramic way at a collection of data and to see with one glance its beginning, end and logically imposing \"jump\" (selection of the next element), as for example in such a&nbsp;chain:<\/p>\n\n\n\n<p>house \u2192 sequence of letters 'h', 'o', 'u', 's', 'e'<\/p>\n\n\n\n<p>Most programming languages therefore require that elements be indexed \u2014 and then indicated with those indexes how \u2014 and how many times \u2014 the loop is to&nbsp;run.<\/p>\n\n\n\n<p>The creators of Python decided to free us from this obligation and invented their brilliant iterators, thanks to which the computer sees the collection like a human: it recognizes its first and last element and is able to perform the magic \"next\" \u2014 jump to the next element until we reach the last element in the collection.<\/p>\n\n\n\n<p><em>You will find quite a lot of articles and studies on iterators on the web. In our opinion, when learning the basics of&nbsp;programming, it makes no sense to explore them. Iterators were invented as \"good spirits\": they are invisible themselves and do their job in invisible way. It is enough for us that thanks to them we can comfortably traverse<a href=\"#_ftn2\"><strong>[2]<\/strong><\/a> the&nbsp;collections.<\/em><\/p>\n\n\n\n<p>Let's have a&nbsp;look.<\/p>\n\n\n\n<p>The classic loop (known from C or C ++ languages) looks something like&nbsp;this:<\/p>\n\n\n\n<p>for(int i=0; i&lt;10;&nbsp;i++)<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp; \u2026do something with A[i]<\/p>\n\n\n\n<p>where A [i] is the i\u2011th element of collection A<\/p>\n\n\n\n<p>As you can see, instead of iterating over the elements directly, we iterate over their indexes.<br>We need to make sure that there are just 10 elements and then limit the range of the loop to that number (i &lt;10).<\/p>\n\n\n\n<p>Contrary to that, the loop in Python<\/p>\n\n\n\n<p>for element in&nbsp;A:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp; do something with element<\/p>\n\n\n\n<p>has the same effect without indexes and without ranges.<\/p>\n\n\n\n<p>The advantage of the Python for loop is its simplicity.<\/p>\n\n\n\n<p><strong>You don't need to count&nbsp;items<\/strong><\/p>\n\n\n\n<p>In Python, the for loop actually works like the foreach loop. As the name suggests, the foreach loop engages each item in the collection in turn. It becomes redundant to determine the number of items in&nbsp;a collection.<\/p>\n\n\n\n<p><strong>Direct access to collection items<\/strong><\/p>\n\n\n\n<p>While in the classic for loop you access the elements of a sequence indirectly \u2014 through their indexes \u2014 the foreach loop gives us direct access to the elements in a collection. Indexes become redundant. The annoying \"hedgehog\" \u2014 that is, the piece of code \"riddled with\" square and round brackets \u2014 disappears.<\/p>\n\n\n\n<p>Let's compare the two mentioned types of&nbsp;loops<\/p>\n\n\n\n<p>While Python favors its elegant indexless loop (which is essentially a foreach loop), in Python we can also easily build a for loop like the classic indexed loop. We will use the functions range() and len(); len() reflects the length of the sequence (number of elements in it) \u2014 so, if you want to go through the whole sequence A, just write in range(len(A)).<\/p>\n\n\n\n<p>This pattern is very eagerly used by students who \"come\" to Python with experience in programming in Java or C ++. Driven by habit, they try to access successive elements (in a set of elements) using indexes. They forget that Python offers a better and simpler way to access the elements of a set that the loop iterates over. Let us look at some examples.<\/p>\n\n\n\n<p>Iterating over indexes (range and len in action)<\/p>\n\n\n\n<p>How many of you often write such&nbsp;code?<\/p>\n\n\n\n<p>animals = ['sheep', 'cow', 'pig', 'horse', 'goat']<\/p>\n\n\n\n<p>for i in range(len(animals)):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp; print(animals[i])<\/p>\n\n\n\n<p>It makes sense, doesn't it? You check the length of the animals list, create a \"range\" object containing the index collection, and then iterate over that collection.<\/p>\n\n\n\n<p>As a result, with the help of these indexes, you get access to the names of the animals. A bit of a roundabout road to the goal, isn't it? And you don't have to do it in such a \"roundabout\" way.<\/p>\n\n\n\n<p>Python gives you a nice shortcut: the \"indexless\" Python for loop \u2014 which is essentially a foreach loop.<\/p>\n\n\n\n<p>Unlike the classic for loop, the foreach loop gives you direct access to the items in the collection. So&nbsp;we can assign these elements directly to the loop variable, instead of looking for help in indices as&nbsp;we did in the example above.<\/p>\n\n\n\n<p>Thus the more Pythonic way of writing a loop might look like&nbsp;this:<\/p>\n\n\n\n<p>animals = ['sheep', 'cow', 'pig', 'horse', 'goat']<\/p>\n\n\n\n<p>for animal in animals:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp; print(animal)<\/p>\n\n\n\n<p>Here instead of abstract variable name: \"i\", we have a nice descriptive variable name, and the code is generally much shorter and less complex.<\/p>\n\n\n\n<p>Please note that using range() function to \"generate\" indexes \u2013 and then accessing element using those indexes \u2013 is not in the spirit of Python. Iterating using indexes is not recommended if we can iterate over the elements directly.<\/p>\n\n\n\n<p>Let's discuss the pros and&nbsp;cons&nbsp;\u2026<\/p>\n\n\n\n<p>Iterating over two lists at&nbsp;once<\/p>\n\n\n\n<p>OK, now comes the question: is it better to iterate directly over the elements of a collection or over their indexes?&nbsp; Well, the answer is not simple. Each solution has its advantages and disadvantages.<\/p>\n\n\n\n<p>For example, you cannot iterate over two lists at the same time with an indexless loop. While with the&nbsp;indexed loop it is possible!<\/p>\n\n\n\n<p>Look at a typical example: list A \u2014 list of net prices, list B \u2014 list of 10% tax. We iterate over A and B simultaneously and create a new list C with the sums: net price +&nbsp;tax<\/p>\n\n\n\n<p>A=[12, 14,&nbsp;16]<\/p>\n\n\n\n<p>B=[1.2, 1.4, 1.6]<\/p>\n\n\n\n<p>C=[]<\/p>\n\n\n\n<p>for i in range(len(A)):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp; C.append(A[i]+B[i])<\/p>\n\n\n\n<p>print\u00a9<\/p>\n\n\n\n<p>Output:<\/p>\n\n\n\n<p>[13.2, 15.4, 17.6]<\/p>\n\n\n\n<p>As you might have guessed, the Python developers found a way to iterate over two lists at once without using indexes. Use the zip function<\/p>\n\n\n\n<p>A=[12, 14,&nbsp;16]<\/p>\n\n\n\n<p>B=[1.2, 1.4, 1.6]<\/p>\n\n\n\n<p>C=[]<\/p>\n\n\n\n<p>for (price, tax) in zip (A,&nbsp;B):<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp; C.append(price+tax)<\/p>\n\n\n\n<p>print\u00a9<\/p>\n\n\n\n<p>Output:<\/p>\n\n\n\n<p>[13.2, 15.4, 17.6]<\/p>\n\n\n\n<p>zip is a simple tool for parallel iteration. It is nice and convenient to use. But supporters of index methods will surely wince: another function to remember \u2026 And it works less intuitively than the variant using indexes&nbsp;\u2026<\/p>\n\n\n\n<p>Changing when iterating<\/p>\n\n\n\n<p>Another consideration when deciding between an indexed loop and an indexless loop is the loop's ability to modify the collection it iterates over. In particular, the ability to change the value of individual elements of the collection.<\/p>\n\n\n\n<p>The indexed for loop has the ability to change the value of the elements of the collection it iterates over. However, an indexless loop does not. Let's explain why.<\/p>\n\n\n\n<p>The indexed loop allows access to the list items \"by index\"; when we therefore have a&nbsp;list:<\/p>\n\n\n\n<p>A = ['cat', 'dog', 'mouse']<\/p>\n\n\n\n<p>the program views it as follows:<\/p>\n\n\n\n<p>&nbsp;A = [A[0] = 'cat', A[1] = 'dog', A[2] = 'mouse')<\/p>\n\n\n\n<p>thus it sees the list items as a collection of variables (labels) with assigned values<a href=\"#_ftn3\">[3]<\/a>. These \"variables\" contain the index against which the value of the element is&nbsp;found.<\/p>\n\n\n\n<p>However, in the case of an indexless loop, the values \u200b\u200b\u2014 which are successive elements of the list \u2014 are assigned to the variable outside the&nbsp;list.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"390\" height=\"138\" src=\"http:\/\/juthon.com\/wp-content\/uploads\/2021\/12\/Pass_10_Tab_01.jpg\" alt class=\"wp-image-193\" srcset=\"http:\/\/juthon.com\/wp-content\/uploads\/2021\/12\/Pass_10_Tab_01.jpg 390w, http:\/\/juthon.com\/wp-content\/uploads\/2021\/12\/Pass_10_Tab_01-300x106.jpg 300w\" sizes=\"(max-width: 390px) 100vw, 390px\"><\/figure>\n\n\n\n<p>This is the crux of the matter. When we ask the for loop to invoke the elements of the list as quasi-variables, the loop can change their values in the list itself. And when we ask the loop to call (find) <strong>a&nbsp;value<\/strong> in a list, we cannot change these values at the same time. At most, we can change them outside the&nbsp;list.<\/p>\n\n\n\n<p>Let's check with examples if it works as described:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>Indexed for&nbsp;loop<\/td><td>Indexless for&nbsp;loop<\/td><\/tr><tr><td>A = ['cat', 'dog', 'mouse'] <br>for i in range(len(A)): &nbsp;&nbsp;&nbsp; <br>    A[i]='parrot' print(A) &nbsp; <br>Output: ['parrot', 'parrot', 'parrot']<\/td><td>A = ['cat', 'dog', 'mouse'] <br>for elem in A: &nbsp;&nbsp;&nbsp; <br>    elem='parrot' print(A) &nbsp; <br>Output: ['cat', 'dog', 'mouse']<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Here you go. Everything turned out to be true \u2014 as announced. The indexed loop has changed the list items. An indexless loop left the list elements unchanged<a href=\"#_ftn4\">[4]<\/a>.<\/p>\n\n\n\n<p>Finally: be very careful when modifying the lists you are iterating through the for loop. Avoid removing or adding items to the list during iteration, because your code may trick&nbsp;you&nbsp;\u2026<\/p>\n\n\n\n<hr class=\"wp-block-separator\">\n\n\n\n<p><a href=\"#_ftnref1\">[1]<\/a> for example, in C ++ it is the function length(), and in Python it is the function len()<\/p>\n\n\n\n<p><a href=\"#_ftnref2\">[2]<\/a> traversing is the process by which you access \u2013 one by one \u2013 every element present in a data structure, such as an&nbsp;array.<\/p>\n\n\n\n<p><a href=\"#_ftnref3\">[3]<\/a> note: the above notation is for illustrative purpose only; do not write list items this&nbsp;way<\/p>\n\n\n\n<p><a href=\"#_ftnref4\">[4]<\/a> another old rule, which you should always remember: in programming, a value (= an immutable object) is a sequence of&nbsp;bits and it involves memory allocation. You can assign a value to a variable. Then, the variable may be reassigned a new value, but the existing value cannot be modified.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this passage, we're continuing to learn the most popular loop in Python: the for&nbsp;loop.&nbsp;[\u2026]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wp_typography_post_enhancements_disabled":false},"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/posts\/192"}],"collection":[{"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/comments?post=192"}],"version-history":[{"count":1,"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/posts\/192\/revisions"}],"predecessor-version":[{"id":194,"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/posts\/192\/revisions\/194"}],"wp:attachment":[{"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/media?parent=192"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/categories?post=192"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/juthon.com\/index.php\/wp-json\/wp\/v2\/tags?post=192"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}