1 00:00:00,965 --> 00:00:01,740 Welcome back. 2 00:00:02,970 --> 00:00:07,195 Previously I should you that a shallow copy it can lead to some confusions 3 00:00:07,195 --> 00:00:11,085 because the same inner lists is included in multiple outer lists. 4 00:00:11,085 --> 00:00:15,051 What would we do if we wanted to make a copy that it was completely independent of 5 00:00:15,051 --> 00:00:16,082 the original list? 6 00:00:16,082 --> 00:00:18,198 So that no change anywhere, 7 00:00:18,198 --> 00:00:22,351 even to a inner list to which change the copied version. 8 00:00:22,351 --> 00:00:25,926 That's what's called a deep copy. 9 00:00:25,926 --> 00:00:30,560 We can do it with nested iteration, accumulating a copy of each inner list. 10 00:00:31,580 --> 00:00:32,960 So let's take a look at this code. 11 00:00:34,260 --> 00:00:40,950 I have the same original list from before, it has two inner lists. 12 00:00:40,950 --> 00:00:43,610 The first one, dogs and puppies, the second one, cats and kittens. 13 00:00:45,240 --> 00:00:48,110 I'm going to use our old friend, the accumulation pattern. 14 00:00:48,110 --> 00:00:52,360 I start by making copied_outer_list be an empty list, 15 00:00:52,360 --> 00:00:57,201 so this is our accumulator variable. 16 00:00:57,201 --> 00:01:02,013 I iterate through the sequence original by loop variable or 17 00:01:02,013 --> 00:01:05,871 iterator variable I'm calling, inner list. 18 00:01:05,871 --> 00:01:09,402 And then I'm doing this nested iteration. 19 00:01:09,402 --> 00:01:12,256 And I'm doing a nested accumulation here. 20 00:01:12,256 --> 00:01:17,142 So I make another accumulated variable, copied_inner_list, and 21 00:01:17,142 --> 00:01:18,723 it's set to be empty. 22 00:01:18,723 --> 00:01:22,358 I iterate through the items in inner list. 23 00:01:22,358 --> 00:01:25,395 Here my second iterator variable is called item. 24 00:01:25,395 --> 00:01:30,201 And I append it, I append item, to the copied_inne_list. 25 00:01:30,201 --> 00:01:34,368 So copied_inner_list starts as an empty list, and 26 00:01:34,368 --> 00:01:37,430 we keep adding additional items to it. 27 00:01:37,430 --> 00:01:40,063 When we're done with the inner list, 28 00:01:40,063 --> 00:01:44,438 copied_inner_list has all of the same elements that it had. 29 00:01:44,438 --> 00:01:49,796 And so we then take copied_inner_ list, and we append it to the outer list. 30 00:01:51,757 --> 00:01:53,916 Let's run that and see what happens. 31 00:01:59,839 --> 00:02:06,104 At the end of lines 337, we have copied_outer_ list as this deep copy. 32 00:02:06,104 --> 00:02:12,106 If we print it, it looks like it has the same contents as original. 33 00:02:12,106 --> 00:02:17,462 Because this is a deep copy, even if I append canines to the end 34 00:02:17,462 --> 00:02:23,539 of the first inner list in the original list, as I'm doing on line 9, 35 00:02:23,539 --> 00:02:29,842 it's not going to have any impact on the deep copy of the copied outer list. 36 00:02:29,842 --> 00:02:32,451 So, we print original, and 37 00:02:32,451 --> 00:02:38,121 it does the same thing that happened in our previous example. 38 00:02:38,121 --> 00:02:42,835 But when I print the copied outer list, there's no canines here 39 00:02:44,538 --> 00:02:48,385 The reason is that I have made a deep copy. 40 00:02:48,385 --> 00:02:52,251 So let's just make the reference diagram that'll go with this. 41 00:02:52,251 --> 00:02:54,519 We have original, 42 00:02:57,228 --> 00:03:01,553 It's a list of two things. 43 00:03:02,822 --> 00:03:07,714 And one is the Dogs and puppies. 44 00:03:15,545 --> 00:03:20,149 The other is the cats and kittens. 45 00:03:27,567 --> 00:03:31,113 When we make a copied_outer_list, 46 00:03:36,584 --> 00:03:40,086 We end up again with a list of two items. 47 00:03:40,086 --> 00:03:45,016 But the first item is now not pointing to dogs and 48 00:03:45,016 --> 00:03:49,339 puppies, it's pointing to a copy of it. 49 00:03:54,601 --> 00:04:03,131 With the same contents, And it's a different list. 50 00:04:03,131 --> 00:04:08,054 So then on line 9, when I append something here, 51 00:04:08,054 --> 00:04:12,636 there's an extra item with the canines in it. 52 00:04:16,607 --> 00:04:23,498 It does not have any effect on the inner list from copied outer list. 53 00:04:23,498 --> 00:04:25,728 Doesn't change anything in the deep copies. 54 00:04:25,728 --> 00:04:29,093 So we have successfully managed to make copiedouter 55 00:04:29,093 --> 00:04:33,915 list be a deep copy that is completely independent from the original list. 56 00:04:33,915 --> 00:04:37,663 Even if I change something deep inside the original list, 57 00:04:37,663 --> 00:04:40,348 it has no impact on the copied outer list. 58 00:04:43,526 --> 00:04:48,182 Now you might have noticed, Lines 4 59 00:04:48,182 --> 00:04:52,750 through 7 are a little bit more complicated than they need to. 60 00:04:52,750 --> 00:04:56,080 I reminded you previously that we can use the slice operator. 61 00:04:56,080 --> 00:04:59,900 And we can do that here to make a copy of the inner list. 62 00:05:01,070 --> 00:05:07,934 So instead of doing a manual accumulation, we can make the copied inner list, 63 00:05:07,934 --> 00:05:14,080 just be inner_list square bracket colon, and get rid of all of this. 64 00:05:15,270 --> 00:05:18,350 And this maybe makes the code a little easier to read, 65 00:05:18,350 --> 00:05:23,880 if you remember that the slice operator with the colon makes a copy of the list. 66 00:05:25,040 --> 00:05:28,350 So, this has exactly the same effect as the code that we did before. 67 00:05:30,420 --> 00:05:34,220 Nested iteration is where we copy each of the inner list, works fine for 68 00:05:34,220 --> 00:05:38,650 making deep copies, if we know how many levels of nesting we have. 69 00:05:38,650 --> 00:05:41,380 And we have a parallel structure everywhere with the same 70 00:05:41,380 --> 00:05:42,120 levels of nesting. 71 00:05:43,620 --> 00:05:45,817 But what about this one? 72 00:05:45,817 --> 00:05:48,734 There are three levels in some places but not everywhere. 73 00:05:50,325 --> 00:05:58,118 We've got an outer list which has as its first element this inner list. 74 00:05:58,118 --> 00:06:03,292 But this inner list has a string canines as its first element, 75 00:06:03,292 --> 00:06:07,385 but a third level of a list as its second element. 76 00:06:07,385 --> 00:06:10,646 So how would you make a deep copy of this one? 77 00:06:10,646 --> 00:06:14,450 This is a case where a technique called recursion will allow us to 78 00:06:14,450 --> 00:06:18,828 write fairly elegant code, but we are not going to teach recursion in this. 79 00:06:18,828 --> 00:06:21,879 It turns out you can get pretty far in writing the applications and 80 00:06:21,879 --> 00:06:24,436 data analysis programs without learning recursion, 81 00:06:24,436 --> 00:06:27,713 because in the most common cases where it's useful, there is built in 82 00:06:27,713 --> 00:06:31,800 function available to use that will do the recursion behind the scenes. 83 00:06:31,800 --> 00:06:33,709 This is one of those cases, 84 00:06:33,709 --> 00:06:38,862 there's a built in function called deep copy, and a module called copy. 85 00:06:38,862 --> 00:06:43,035 So I've imported the module called copy, and 86 00:06:43,035 --> 00:06:47,850 inside the copy module there is a deep copy function, 87 00:06:47,850 --> 00:06:52,770 and it just takes the sequence as its value. 88 00:06:52,770 --> 00:06:58,569 And it produces a deep copy where as many levels of nesting as there are, 89 00:06:58,569 --> 00:07:01,565 it goes in and always copies things, 90 00:07:01,565 --> 00:07:07,187 it never shares an inner list between the original and the deep copy. 91 00:07:07,187 --> 00:07:10,371 So I have my original version. 92 00:07:13,032 --> 00:07:15,853 I have a shallow copied version, 93 00:07:21,065 --> 00:07:23,575 And I have a deeply copied version. 94 00:07:30,438 --> 00:07:35,843 And if I were to print those out, they would all look the same. 95 00:07:35,843 --> 00:07:44,061 But now I'm going to append to the original an extra string at the very end, 96 00:07:44,061 --> 00:07:48,896 so it's going to have another item at the end. 97 00:07:48,896 --> 00:07:52,671 And then I'm also on line 6 going to the first 98 00:07:55,616 --> 00:08:01,062 In our list, and I'm appending the list marsupials to it. 99 00:08:01,062 --> 00:08:04,022 At this point we're going to have original deep copy and 100 00:08:04,022 --> 00:08:06,338 shallow copy all have different values. 101 00:08:06,338 --> 00:08:07,565 And let's see what those are. 102 00:08:13,425 --> 00:08:18,430 So you can see now that original has canines, 103 00:08:18,430 --> 00:08:24,501 dogs, puppies, and an extra element, marsupials. 104 00:08:24,501 --> 00:08:29,850 That happened because unlike 6, we appended the list 105 00:08:29,850 --> 00:08:34,396 marsupials to the end of its first inner list. 106 00:08:34,396 --> 00:08:39,544 The shallow copy because it only did the one level of copying, 107 00:08:39,544 --> 00:08:43,407 also was changed, it got marsupials as well. 108 00:08:43,407 --> 00:08:46,834 But in the deep copy, no marsupials. 109 00:08:49,432 --> 00:08:53,986 The other difference we can see is that the original and 110 00:08:53,986 --> 00:09:00,131 the shallow copy diverge, because the original gets Hi there at the end. 111 00:09:00,131 --> 00:09:02,818 So we appended to the top level list, and 112 00:09:02,818 --> 00:09:06,542 there the original is different than the shallow copy. 113 00:09:06,542 --> 00:09:11,299 So Hi there got appended to original, did not get appended to shallow copy. 114 00:09:13,637 --> 00:09:16,518 I encourage you to really work through this in detail. 115 00:09:16,518 --> 00:09:18,136 Make a reference diagram. 116 00:09:18,136 --> 00:09:20,051 Go through it in code lens. 117 00:09:20,051 --> 00:09:23,966 Make sure you understand why these things are coming out with 118 00:09:23,966 --> 00:09:26,508 three different printouts at the end. 119 00:09:26,508 --> 00:09:31,441 If you can follow it, you'll be able to reason your way through lot of things 120 00:09:31,441 --> 00:09:36,162 where you get puzzling answers, and you'll be able to debug your code. 121 00:09:36,162 --> 00:09:40,869 So to summarize, a deep copy of a list not only makes a copy of the outer list, but 122 00:09:40,869 --> 00:09:43,350 also makes copies of all the inner lists. 123 00:09:43,350 --> 00:09:46,176 And their inner list all the way down. 124 00:09:46,176 --> 00:09:49,730 A deep copy is completely decoupled from the original. 125 00:09:49,730 --> 00:09:54,416 You can make a deep copy with your own code if the structure is simple enough, or 126 00:09:54,416 --> 00:09:57,684 use the built in deep copy function in the copy module. 127 00:09:57,684 --> 00:09:58,540 See you next time.