WEBVTT 1 00:00:00.370 --> 00:00:01.930 Hi, welcome back. 2 00:00:01.930 --> 00:00:03.610 In this video, we're going to be implementing 3 00:00:03.610 --> 00:00:07.170 our milestone project two using our in-memory database, 4 00:00:07.170 --> 00:00:08.933 which is a Python list. 5 00:00:09.770 --> 00:00:11.640 I really hope you did give it a go 6 00:00:11.640 --> 00:00:13.030 following the project brief 7 00:00:13.030 --> 00:00:15.560 and you tried to implement this project on your own, 8 00:00:15.560 --> 00:00:18.370 and hopefully you succeeded and made it work. 9 00:00:18.370 --> 00:00:20.290 You can always ask questions in the course Q&A 10 00:00:20.290 --> 00:00:23.140 if you need help with anything specific before moving on. 11 00:00:24.020 --> 00:00:25.140 But now that you're here, 12 00:00:25.140 --> 00:00:26.960 let's go and implement this project 13 00:00:26.960 --> 00:00:29.923 using list as our in-memory database. 14 00:00:31.440 --> 00:00:33.240 Of course, the first thing we'll do 15 00:00:33.240 --> 00:00:35.270 is define the user interface 16 00:00:35.270 --> 00:00:37.260 so that the user can interact with our programme 17 00:00:37.260 --> 00:00:39.893 and then we can add functionality little by little. 18 00:00:41.771 --> 00:00:43.880 The first thing we've got is we ask the user 19 00:00:43.880 --> 00:00:45.350 to enter their choice. 20 00:00:45.350 --> 00:00:48.620 That's a, l, r, d, or q. 21 00:00:48.620 --> 00:00:51.290 If they enter q, we're not gonna go into this loop, 22 00:00:51.290 --> 00:00:54.623 so in here we have to deal with four options, 23 00:00:55.500 --> 00:00:57.723 if the user_input is a, 24 00:00:59.690 --> 00:01:01.763 if the user_input is l, 25 00:01:03.220 --> 00:01:06.003 if the user_input is r, 26 00:01:07.420 --> 00:01:10.453 and if the user_input is d. 27 00:01:12.110 --> 00:01:14.870 And if there's none of them, we can print 28 00:01:14.870 --> 00:01:16.500 Unknown command. 29 00:01:16.500 --> 00:01:17.653 Please try again. 30 00:01:19.590 --> 00:01:20.540 Okay. 31 00:01:20.540 --> 00:01:22.970 Now, of course, in order to go back to the top of the loop 32 00:01:22.970 --> 00:01:24.670 with a different user_input, 33 00:01:24.670 --> 00:01:28.090 we must reset the user_input to something else. 34 00:01:28.090 --> 00:01:31.120 For that, we're going to ask the user again, 35 00:01:31.120 --> 00:01:34.800 but make sure that that's not inside the else or anywhere, 36 00:01:34.800 --> 00:01:36.630 just here within the loop, 37 00:01:36.630 --> 00:01:38.393 outside of any of these statements. 38 00:01:41.822 --> 00:01:42.940 I also gave you a few hints 39 00:01:42.940 --> 00:01:45.860 of what you could call your functions, 40 00:01:45.860 --> 00:01:48.380 so I'm just going to use those names here. 41 00:01:48.380 --> 00:01:51.150 So I'm going to call prompt_add_book(), 42 00:01:51.150 --> 00:01:54.740 the function that doesn't exist yet, when they type a. 43 00:01:54.740 --> 00:01:57.360 We're gonna call list_books() when they type l, 44 00:01:57.360 --> 00:02:01.120 prompt_read_book() when they type r, 45 00:02:01.120 --> 00:02:04.490 and prompt_delete_book() when they type d. 46 00:02:04.490 --> 00:02:07.370 The reason why these functions have prompt in front of them 47 00:02:07.370 --> 00:02:10.170 is because these functions aren't just gonna do things. 48 00:02:10.170 --> 00:02:12.550 They're also going to ask the user for something, 49 00:02:12.550 --> 00:02:14.640 and that's just my way of telling myself 50 00:02:14.640 --> 00:02:16.280 these functions are gonna ask the user. 51 00:02:16.280 --> 00:02:18.460 They have to ask the user for some information 52 00:02:18.460 --> 00:02:20.510 in order to do what they wanna do. 53 00:02:20.510 --> 00:02:21.420 If you wanna add a book, 54 00:02:21.420 --> 00:02:23.300 you have to ask the user for the name and author. 55 00:02:23.300 --> 00:02:24.530 If you wanna read a book, 56 00:02:24.530 --> 00:02:26.410 you have to ask the user at least for the name. 57 00:02:26.410 --> 00:02:27.550 And if you wanna delete a book, 58 00:02:27.550 --> 00:02:29.700 you also have to ask at least for the name. 59 00:02:31.378 --> 00:02:35.243 Okay, so let's go ahead and implement our functions. 60 00:02:36.270 --> 00:02:38.640 Python styling suggests we leave two blank lines 61 00:02:38.640 --> 00:02:41.090 between two functions, so we're gonna do just that, 62 00:02:41.090 --> 00:02:42.450 and then we're going to define 63 00:02:42.450 --> 00:02:45.820 our prompt_add_book() function. 64 00:02:45.820 --> 00:02:46.653 What this is gonna do 65 00:02:46.653 --> 00:02:48.590 is ask the user for name and author. 66 00:02:48.590 --> 00:02:49.423 So name 67 00:02:53.455 --> 00:02:54.373 and the author, 68 00:02:58.470 --> 00:03:00.150 and then all it's gonna do 69 00:03:00.150 --> 00:03:03.554 is ask the database to save this book. 70 00:03:03.554 --> 00:03:05.500 Notice how it's not going to interact 71 00:03:05.500 --> 00:03:07.940 with the books list directly, 72 00:03:07.940 --> 00:03:09.720 but it's going to ask the database 73 00:03:09.720 --> 00:03:11.853 to save the book to the list. 74 00:03:12.860 --> 00:03:15.407 So what to do here is say database.add_book(), 75 00:03:16.560 --> 00:03:17.903 name and author. 76 00:03:18.951 --> 00:03:22.780 Now when we call this, we pass the value of name, a string, 77 00:03:22.780 --> 00:03:24.740 and the value of author, another string, 78 00:03:24.740 --> 00:03:27.320 to our add_book function, 79 00:03:27.320 --> 00:03:30.730 and this is now going to use this global variable 80 00:03:30.730 --> 00:03:34.970 to append this dictionary, which represents our book. 81 00:03:34.970 --> 00:03:36.780 It has a name, an author, 82 00:03:36.780 --> 00:03:40.300 and a read status which starts off as False. 83 00:03:40.300 --> 00:03:42.650 We're going to be able to change this later on. 84 00:03:44.490 --> 00:03:45.323 Okay. 85 00:03:46.229 --> 00:03:48.320 Now we can delete our first comment 86 00:03:48.320 --> 00:03:50.720 for we've already accomplished it. 87 00:03:50.720 --> 00:03:54.113 Once again, leaving two lines, we can say list_books(). 88 00:03:55.780 --> 00:03:58.660 And the list_books() is just going to ask the database 89 00:03:58.660 --> 00:03:59.510 for all the books 90 00:04:03.940 --> 00:04:06.840 and it's going to print them off one by one. 91 00:04:06.840 --> 00:04:09.783 So for book in books, 92 00:04:11.180 --> 00:04:14.600 we're gonna print some representation of the book. 93 00:04:14.600 --> 00:04:15.950 We can do that later. 94 00:04:15.950 --> 00:04:17.630 For right now, we're just going to print the dictionary 95 00:04:17.630 --> 00:04:18.690 that will come back. 96 00:04:18.690 --> 00:04:20.650 Remember, we're storing dictionaries. 97 00:04:20.650 --> 00:04:22.640 Dictionaries are gonna come back. 98 00:04:22.640 --> 00:04:25.130 The get_all_books() function does not exist, 99 00:04:25.130 --> 00:04:27.330 so we're going to create it in the database. 100 00:04:32.660 --> 00:04:35.150 And what should this function do? 101 00:04:35.150 --> 00:04:36.550 Well, in order to get all the books, 102 00:04:36.550 --> 00:04:38.660 all it has to do is return this list here 103 00:04:38.660 --> 00:04:40.720 that will contain all our books, 104 00:04:40.720 --> 00:04:43.083 so just return books will do. 105 00:04:44.250 --> 00:04:48.100 When we set up this programme and work with files, 106 00:04:48.100 --> 00:04:50.110 this is going to get more complicated, of course. 107 00:04:50.110 --> 00:04:52.590 It's going to have to actually open a file 108 00:04:52.590 --> 00:04:53.980 and read the contents. 109 00:04:53.980 --> 00:04:55.860 And suddenly when we move on to databases, 110 00:04:55.860 --> 00:04:57.340 it's gonna get even more complicated, 111 00:04:57.340 --> 00:04:59.430 as we will have to connect to the database 112 00:04:59.430 --> 00:05:00.870 and retrieve the data. 113 00:05:00.870 --> 00:05:02.350 But for now, because we're using 114 00:05:02.350 --> 00:05:04.450 a simple in-memory database, 115 00:05:04.450 --> 00:05:06.200 we can just return the books there. 116 00:05:08.290 --> 00:05:11.710 Now we can delete our list_books() comment there 117 00:05:11.710 --> 00:05:13.460 since we've already implemented it. 118 00:05:14.580 --> 00:05:17.660 Let's move on to prompt_read_book(), 119 00:05:17.660 --> 00:05:19.840 and this has to ask for the book name 120 00:05:19.840 --> 00:05:23.350 and then go to the database and change it to read. 121 00:05:23.350 --> 00:05:24.523 So name, 122 00:05:30.283 --> 00:05:33.020 Enter the name of the book you just finished reading, 123 00:05:33.020 --> 00:05:34.940 and then all we wanna do is say 124 00:05:34.940 --> 00:05:39.352 database.mark_book_as_read with that name. 125 00:05:39.352 --> 00:05:41.590 Of course, this function does not exist, 126 00:05:41.590 --> 00:05:46.265 so we have to go over to our database.py and define that. 127 00:05:46.265 --> 00:05:48.960 mark_book_as_read(), 128 00:05:48.960 --> 00:05:51.240 and it is given a name. 129 00:05:51.240 --> 00:05:53.760 This parameter here will receive the string 130 00:05:53.760 --> 00:05:54.910 that the user entered, 131 00:05:54.910 --> 00:05:57.280 and that should be the name of the book. 132 00:05:57.280 --> 00:05:59.680 So how would we mark a book as read, 133 00:05:59.680 --> 00:06:01.653 knowing that we have a list of books? 134 00:06:02.581 --> 00:06:04.240 If you didn't try this before, 135 00:06:04.240 --> 00:06:06.380 then I hope you pause the video there for a moment 136 00:06:06.380 --> 00:06:07.720 and give it a go. 137 00:06:07.720 --> 00:06:10.990 All to do is just iterate over the books, 138 00:06:10.990 --> 00:06:13.263 and if the book was read, 139 00:06:13.263 --> 00:06:16.483 if book is equal to the name that we gave it, 140 00:06:17.770 --> 00:06:19.260 then say book 141 00:06:20.760 --> 00:06:22.483 read is now True. 142 00:06:25.720 --> 00:06:26.953 Okay, that's it. 143 00:06:26.953 --> 00:06:29.380 Just go over the books and for each book, 144 00:06:29.380 --> 00:06:32.150 modify it if the name matches. 145 00:06:32.150 --> 00:06:34.660 Of course, this does suggest that if two books 146 00:06:34.660 --> 00:06:35.493 have the same name, 147 00:06:35.493 --> 00:06:38.080 they're both going to be changed over to be read, 148 00:06:38.080 --> 00:06:42.260 but, you know, we can deal with that problem later on. 149 00:06:42.260 --> 00:06:43.960 If you want, of course, you can change this 150 00:06:43.960 --> 00:06:46.420 to take two arguments, the name and the author, 151 00:06:46.420 --> 00:06:50.053 and that gives you a bit more granularity in what you do. 152 00:06:53.130 --> 00:06:55.250 Finally, we're going to delete this comment here 153 00:06:55.250 --> 00:06:57.050 and define the prompt_delete_book(). 154 00:07:00.226 --> 00:07:02.503 Once again, this is going to take a name, 155 00:07:09.049 --> 00:07:14.040 and it's going to do database.delete_book() with that name. 156 00:07:14.040 --> 00:07:15.900 Naturally, that also doesn't exist, 157 00:07:15.900 --> 00:07:18.120 so once again we go to our database 158 00:07:18.120 --> 00:07:19.723 and we define that function. 159 00:07:23.370 --> 00:07:25.070 So how may we do that? 160 00:07:25.070 --> 00:07:28.163 This is a slightly more interesting thing. 161 00:07:29.180 --> 00:07:33.010 There are few ways in which we could delete a book. 162 00:07:33.010 --> 00:07:35.810 Pause the video and give it a go if you haven't already. 163 00:07:40.260 --> 00:07:42.660 One way that my students frequently come up 164 00:07:42.660 --> 00:07:45.450 with removing a book is by going over 165 00:07:45.450 --> 00:07:49.480 to the list documentation and see where the list 166 00:07:49.480 --> 00:07:51.823 have any way of removing elements from them. 167 00:07:52.795 --> 00:07:54.950 And normally we end up with this. 168 00:07:54.950 --> 00:07:56.730 Go through each book. 169 00:07:56.730 --> 00:07:59.363 If the name matches what we want to delete, 170 00:08:00.450 --> 00:08:03.950 then do books.remove(book) 171 00:08:03.950 --> 00:08:08.950 because the list objects have this .remove method in them 172 00:08:09.136 --> 00:08:12.550 and they take one of the objects in the list 173 00:08:12.550 --> 00:08:15.500 and allows you to remove the object entirely from the list. 174 00:08:16.530 --> 00:08:18.433 So this would certainly work. 175 00:08:19.910 --> 00:08:23.970 However, it is generally considered bad practise 176 00:08:23.970 --> 00:08:28.958 to modify a list while you iterate over it. 177 00:08:28.958 --> 00:08:32.000 That's because as you go from one element to the next, 178 00:08:32.000 --> 00:08:35.177 elements are disappearing, Python will get a bit confused, 179 00:08:35.177 --> 00:08:38.890 so generally not a good idea to remove elements from a list 180 00:08:38.890 --> 00:08:40.988 while you iterate over it. 181 00:08:40.988 --> 00:08:42.900 However, this is a way that you could do it 182 00:08:42.900 --> 00:08:45.450 and it would work in the majority of circumstances. 183 00:08:46.780 --> 00:08:48.240 Instead, I would 184 00:08:49.900 --> 00:08:50.733 do this. 185 00:08:52.080 --> 00:08:53.300 The first thing we wanna do 186 00:08:53.300 --> 00:08:56.893 is say books is equal to, no, that's our variable up there, 187 00:08:57.850 --> 00:08:59.530 and now we're gonna use a list comprehension 188 00:08:59.530 --> 00:09:01.437 with a conditional. 189 00:09:01.437 --> 00:09:03.010 A list comprehension with a conditional 190 00:09:03.010 --> 00:09:07.810 is going to go adding each book over to this new list 191 00:09:07.810 --> 00:09:09.800 if the book's name is not equal 192 00:09:09.800 --> 00:09:12.230 to the name we got as an argument. 193 00:09:12.230 --> 00:09:14.180 Add each book 194 00:09:14.180 --> 00:09:17.225 to new list if book name 195 00:09:17.225 --> 00:09:20.107 is not equal to the name argument that we got here, 196 00:09:20.107 --> 00:09:21.803 the name parameter, sorry. 197 00:09:21.803 --> 00:09:24.250 Once again, I'd encourage you to pause the video 198 00:09:24.250 --> 00:09:27.320 and give this list comprehension a go just for practise. 199 00:09:27.320 --> 00:09:28.850 Make sure that you've not forgotten 200 00:09:28.850 --> 00:09:30.783 how to implement list comprehensions. 201 00:09:30.783 --> 00:09:32.930 And if you have, then continue watching 202 00:09:32.930 --> 00:09:34.230 and we shall implement it. 203 00:09:39.080 --> 00:09:41.000 Okay, I hope you got that. 204 00:09:41.000 --> 00:09:43.160 But if you didn't, that's totally fine. 205 00:09:43.160 --> 00:09:45.080 All we wanna do is create a variable 206 00:09:46.330 --> 00:09:48.550 for book in books 207 00:09:48.550 --> 00:09:50.250 and then we only want to put it inside the list. 208 00:09:50.250 --> 00:09:53.280 Remember, this is the value we're putting in our new list 209 00:09:54.240 --> 00:09:55.480 if the book name 210 00:09:56.315 --> 00:09:58.410 is not equal to the name argument. 211 00:09:58.410 --> 00:10:00.200 I'm gonna delete this comment now from there 212 00:10:00.200 --> 00:10:01.873 since we don't need it any longer. 213 00:10:02.780 --> 00:10:05.880 So this is going to put the book element into a new list 214 00:10:06.880 --> 00:10:09.800 for book in books, which is our list, 215 00:10:09.800 --> 00:10:12.973 if the book's name is not equal to the parameter. 216 00:10:13.810 --> 00:10:16.960 But, of course, Python doesn't quite like this 217 00:10:16.960 --> 00:10:21.010 and there's a really good reason why I'm getting a red line 218 00:10:21.010 --> 00:10:23.930 and this is something that you should preempt against 219 00:10:23.930 --> 00:10:25.858 and you should understand. 220 00:10:25.858 --> 00:10:27.790 The reason why it's giving me a red line 221 00:10:27.790 --> 00:10:29.670 is because of a concept of scope. 222 00:10:29.670 --> 00:10:31.960 Once again, I did mention that scope would appear 223 00:10:31.960 --> 00:10:33.700 throughout the course a number of times, 224 00:10:33.700 --> 00:10:36.923 and this is an important scenario for understanding scope. 225 00:10:37.910 --> 00:10:39.000 What we've got now 226 00:10:39.000 --> 00:10:41.923 is we have a global variable called books. 227 00:10:43.380 --> 00:10:45.670 However, Python has also created 228 00:10:45.670 --> 00:10:47.790 a local variable to this function. 229 00:10:47.790 --> 00:10:52.140 This variable books only exist within this function here 230 00:10:52.140 --> 00:10:53.770 and it is not the same variable 231 00:10:53.770 --> 00:10:55.623 as the global variable books. 232 00:10:57.809 --> 00:11:00.600 So now it thinks that we are setting this variable, 233 00:11:00.600 --> 00:11:02.860 we're creating this new variable books, 234 00:11:02.860 --> 00:11:06.890 but we are also using it in the statement that creates it. 235 00:11:06.890 --> 00:11:09.030 And this is obviously nonsensical 236 00:11:09.030 --> 00:11:12.060 because this variable doesn't exist yet 237 00:11:12.060 --> 00:11:14.223 since it's being created in that same line. 238 00:11:15.180 --> 00:11:16.790 What we have to do is tell Python 239 00:11:16.790 --> 00:11:18.830 that we don't wanna create a new variable. 240 00:11:18.830 --> 00:11:21.453 We want to use the global variable books. 241 00:11:22.990 --> 00:11:26.850 Another option will be to rename this variable books_new, 242 00:11:26.850 --> 00:11:28.440 as that, and then it doesn't complain anymore 243 00:11:28.440 --> 00:11:32.060 because it realises that this variable we're using 244 00:11:32.060 --> 00:11:33.430 must already exist. 245 00:11:33.430 --> 00:11:35.611 So instead of looking in the local scope, 246 00:11:35.611 --> 00:11:37.990 it looks in the global scope. 247 00:11:37.990 --> 00:11:39.380 However, we don't want to do that 248 00:11:39.380 --> 00:11:42.380 because we want to change this variable. 249 00:11:42.380 --> 00:11:44.270 In order to do so, we must tell Python 250 00:11:44.270 --> 00:11:47.230 that we are looking to use a global variable, 251 00:11:47.230 --> 00:11:49.000 and that's really straightforward. 252 00:11:49.000 --> 00:11:51.440 We just do global books. 253 00:11:51.440 --> 00:11:54.150 What this does essentially is say books 254 00:11:54.150 --> 00:11:57.800 in the local scope is equal to books in the outer scope, 255 00:11:57.800 --> 00:11:59.250 makes them the same, 256 00:11:59.250 --> 00:12:01.760 and then we can use it as normal. 257 00:12:01.760 --> 00:12:04.630 Now it knows that when we use this variable, 258 00:12:04.630 --> 00:12:07.060 we refer to the outer variable. 259 00:12:07.060 --> 00:12:07.970 And similarly here, 260 00:12:07.970 --> 00:12:10.580 we're also referring to the outer variable. 261 00:12:10.580 --> 00:12:12.610 So we're not looking to create a variable 262 00:12:12.610 --> 00:12:13.793 in the local scope. 263 00:12:16.060 --> 00:12:16.893 Okay. 264 00:12:17.773 --> 00:12:19.550 That's it for deleting books, 265 00:12:19.550 --> 00:12:22.923 so we can go back to our app.py and delete our last comment. 266 00:12:23.760 --> 00:12:26.747 And now we have our application completed. 267 00:12:26.747 --> 00:12:28.850 Of course, I went through this quite quickly. 268 00:12:28.850 --> 00:12:31.310 I'd expect you to take substantially longer 269 00:12:31.310 --> 00:12:33.950 the first time that you develop this, 270 00:12:33.950 --> 00:12:35.600 as per the brief, 271 00:12:35.600 --> 00:12:37.237 but if you've gotten this far, 272 00:12:37.237 --> 00:12:39.910 now you hopefully understand what's involved 273 00:12:39.910 --> 00:12:41.393 in making this app. 274 00:12:42.300 --> 00:12:45.253 We just have to get the data from the user, 275 00:12:46.240 --> 00:12:48.243 create dictionaries for the books, 276 00:12:49.190 --> 00:12:51.050 and then store them in a list. 277 00:12:51.050 --> 00:12:52.650 Each of the other operations 278 00:12:52.650 --> 00:12:55.220 is just going to go through our books and change them, 279 00:12:55.220 --> 00:12:56.750 go through our books and delete them, 280 00:12:56.750 --> 00:12:58.563 or just let the user read them. 281 00:13:01.600 --> 00:13:03.310 I'm just going to make a small improvement 282 00:13:03.310 --> 00:13:05.300 in the list_books() function. 283 00:13:05.300 --> 00:13:07.640 I'm going to print something a bit nicer. 284 00:13:07.640 --> 00:13:08.690 So I'm going to print 285 00:13:10.450 --> 00:13:12.460 the book's name. 286 00:13:12.460 --> 00:13:15.720 Now, of course, when you use the single quotes 287 00:13:15.720 --> 00:13:18.060 inside a dictionary and you've got single quotes outside 288 00:13:18.060 --> 00:13:20.100 in your left string, it doesn't like that, 289 00:13:20.100 --> 00:13:22.870 so I'm gonna use double quotes on the outside 290 00:13:22.870 --> 00:13:25.943 and just for Python's benefit. 291 00:13:29.780 --> 00:13:32.183 I'm gonna say book name by book author, 292 00:13:33.270 --> 00:13:35.120 and read is gonna be 293 00:13:36.040 --> 00:13:37.453 book read. 294 00:13:39.520 --> 00:13:40.660 So this is gonna be something 295 00:13:40.660 --> 00:13:42.250 like 296 00:13:42.250 --> 00:13:45.100 Fluent Python by the author, 297 00:13:45.100 --> 00:13:46.790 read False 298 00:13:46.790 --> 00:13:47.910 or True. 299 00:13:47.910 --> 00:13:50.123 In my case, it's False, I haven't read it yet. 300 00:13:51.460 --> 00:13:54.400 Okay, the author is, by the way, Luciano Ramalho. 301 00:13:54.400 --> 00:13:55.413 I think that's how you say his name. 302 00:13:55.413 --> 00:13:56.246 It's a good book. 303 00:13:56.246 --> 00:13:57.170 You should read it. 304 00:13:58.470 --> 00:14:00.873 So now we've got the name and the author. 305 00:14:01.850 --> 00:14:03.490 And read, is it a True or False? 306 00:14:03.490 --> 00:14:05.380 If we wanna make that a bit nicer, 307 00:14:05.380 --> 00:14:09.793 we can say something like read is YES if book read, 308 00:14:11.000 --> 00:14:11.833 else 309 00:14:12.770 --> 00:14:14.130 NO. 310 00:14:14.130 --> 00:14:16.690 This is a ternary statement in Python. 311 00:14:16.690 --> 00:14:20.330 It just means use this value if this is True, 312 00:14:20.330 --> 00:14:23.890 otherwise use this value here for assigning to the variable. 313 00:14:23.890 --> 00:14:27.160 So if book read is True, it's going to say YES, 314 00:14:27.160 --> 00:14:30.810 if book read is False, it's going to say NO. 315 00:14:30.810 --> 00:14:34.430 And remember, this is essentially the same as this. 316 00:14:34.430 --> 00:14:37.210 Book read is True, you can remove the is True 317 00:14:37.210 --> 00:14:40.060 as we looked at in the very first section of this course. 318 00:14:41.240 --> 00:14:43.810 Now instead of book read, we can just use read 319 00:14:44.670 --> 00:14:46.920 since that's the variable we've created here. 320 00:14:48.430 --> 00:14:52.083 Okay, let's go and run our app and see what happens. 321 00:14:54.410 --> 00:14:55.270 Nothing. 322 00:14:55.270 --> 00:14:57.980 Of course, we've not ran the menu() function. 323 00:14:57.980 --> 00:14:59.880 So let's go over down to the very bottom 324 00:14:59.880 --> 00:15:03.200 and run the menu() function, and now we see our input. 325 00:15:03.200 --> 00:15:05.510 I'm just going to extend this a little bit. 326 00:15:05.510 --> 00:15:08.010 We can add a new book. 327 00:15:08.010 --> 00:15:11.360 Let's say, for example, Clean Code is a good book as well. 328 00:15:11.360 --> 00:15:12.550 You can also read it. 329 00:15:12.550 --> 00:15:14.360 It's by Robert C. Martin. 330 00:15:14.360 --> 00:15:15.543 Martin. 331 00:15:17.240 --> 00:15:18.250 And that's it. 332 00:15:18.250 --> 00:15:19.140 We've added it. 333 00:15:19.140 --> 00:15:21.723 Now we can press l to see them 334 00:15:21.723 --> 00:15:25.693 and we get Clean Code by Robert C. Martin, read NO. 335 00:15:26.810 --> 00:15:28.390 We can add another one. 336 00:15:28.390 --> 00:15:30.363 Let's say, for example, 337 00:15:31.690 --> 00:15:33.480 Test Driven Development 338 00:15:34.390 --> 00:15:36.150 by Kent Beck. 339 00:15:36.150 --> 00:15:37.463 Also a good book. 340 00:15:37.463 --> 00:15:39.480 Now we can list them 341 00:15:39.480 --> 00:15:42.130 and we can see that we've not read either Clean Code 342 00:15:42.130 --> 00:15:44.790 or Test Driven Development, but we want to. 343 00:15:44.790 --> 00:15:46.500 So let's go ahead and read Clean Code first. 344 00:15:46.500 --> 00:15:48.080 So we type r, 345 00:15:48.080 --> 00:15:50.480 and, by the way, add a space after your choice. 346 00:15:50.480 --> 00:15:52.340 It's just poor planning on my part. 347 00:15:52.340 --> 00:15:53.591 It just looks awful. 348 00:15:53.591 --> 00:15:55.780 Enter the name of the book you just finished reading. 349 00:15:55.780 --> 00:15:57.356 Let's say Clean Code. 350 00:15:57.356 --> 00:15:59.550 Now we can list the books again 351 00:15:59.550 --> 00:16:01.453 and we see that Clean Code says YES. 352 00:16:02.900 --> 00:16:06.343 Of course, when we quit and we start again, 353 00:16:08.760 --> 00:16:09.940 we don't have any books 354 00:16:09.940 --> 00:16:13.480 because we've stored them in an in-memory database. 355 00:16:13.480 --> 00:16:15.450 That is a database that lives in memory, 356 00:16:15.450 --> 00:16:17.958 in the memory of our computer, which is volatile 357 00:16:17.958 --> 00:16:21.520 and is only available for as long as the app is running. 358 00:16:21.520 --> 00:16:23.142 As soon as we stop running, 359 00:16:23.142 --> 00:16:27.849 the database gets erased by Python to save memory. 360 00:16:27.849 --> 00:16:29.120 We don't want this. 361 00:16:29.120 --> 00:16:32.580 So what we want to do is go ahead 362 00:16:32.580 --> 00:16:35.123 and use a file instead. 363 00:16:36.170 --> 00:16:38.340 And now you understand why 364 00:16:39.420 --> 00:16:42.060 I have tried to decouple our database 365 00:16:42.980 --> 00:16:45.000 from our app. 366 00:16:45.000 --> 00:16:46.250 Now 367 00:16:46.250 --> 00:16:50.941 nearly all the changes are going to be in the database file 368 00:16:50.941 --> 00:16:55.693 for us to swap over to files instead of in-memory database. 369 00:16:56.640 --> 00:16:57.543 Here's an example. 370 00:16:59.170 --> 00:17:01.940 books is now not going to be a list any longer. 371 00:17:01.940 --> 00:17:03.990 It's going to be a file name. 372 00:17:03.990 --> 00:17:07.103 For example, books.txt. 373 00:17:07.103 --> 00:17:09.740 add_book is going to open the file 374 00:17:09.740 --> 00:17:12.353 and it's going to append a book to it. 375 00:17:13.371 --> 00:17:15.740 get_all_books() is going to read the file 376 00:17:15.740 --> 00:17:17.870 and return all the books in it. 377 00:17:17.870 --> 00:17:21.083 mark_books_as_read is going to read all the books. 378 00:17:21.083 --> 00:17:22.600 It's going to change one 379 00:17:22.600 --> 00:17:24.920 and it's going to rewrite them to the file. 380 00:17:24.920 --> 00:17:27.430 And delete_book is going to read all the books, 381 00:17:27.430 --> 00:17:28.660 is going to delete one, 382 00:17:28.660 --> 00:17:30.610 and is going to rewrite it to the file. 383 00:17:32.290 --> 00:17:35.760 You can store the books in CSV format or in JSON format. 384 00:17:35.760 --> 00:17:36.837 It's up to you. 385 00:17:36.837 --> 00:17:38.560 Of course, if you store them in JSON, 386 00:17:38.560 --> 00:17:39.790 it's slightly easier to work with 387 00:17:39.790 --> 00:17:42.060 since we've already worked with dictionaries here. 388 00:17:42.060 --> 00:17:43.440 But if you store them in CSV, 389 00:17:43.440 --> 00:17:45.980 it's not much more difficult either. 390 00:17:45.980 --> 00:17:47.810 In the next video, we're going to go over 391 00:17:47.810 --> 00:17:51.653 changing this to use CSVs, so I'll see you there.