WEBVTT 1 00:00:02.070 --> 00:00:06.210 so as I mentioned the album classes uses a list to store the songs and provides a 2 00:00:06.210 --> 00:00:11.360 method the add song method that we've create for adding more songs or 3 00:00:11.360 --> 00:00:15.499 adding songs to the list and it's also got a field for the artist and we 4 00:00:15.499 --> 00:00:18.699 got an error at the moment and that's because we haven't created that class so we are going 5 00:00:18.699 --> 00:00:24.310 to be doing that in this video now having an artists object stored in the album object can cause 6 00:00:24.310 --> 00:00:29.669 problems because the artist class will also hold the list of the artists publish albums but 7 00:00:29.669 --> 00:00:33.790 I'm gonna talk more about that when we've seen the artist class now one thing worth 8 00:00:33.790 --> 00:00:38.110 mentioning that before we get to that is that the error in the doc string and that is up 9 00:00:38.110 --> 00:00:43.250 here you can see that if we flag is it says unresolved reference album_name so this 10 00:00:43.250 --> 00:00:46.879 really highlights the fact that the doc strings aren't just ordinary strings but they 11 00:00:46.879 --> 00:00:51.300 really do have a special significance looking at the init method as you can 12 00:00:51.300 --> 00:00:56.739 see here on line 30 or 30 downwards we can see that the data attributes of the 13 00:00:56.739 --> 00:01:03.320 class a name year artist and tracks but I incorrectly referred to the album_name 14 00:01:03.320 --> 00:01:08.950 attribute in the doc string so IntelliJ has flag a warning unresolved reference album_ 15 00:01:08.950 --> 00:01:13.380 name so it's unusual for the content of strings to be check for 16 00:01:13.380 --> 00:01:17.960 syntax errors but doc strings are used by a number of tools including IntelliJ 17 00:01:17.960 --> 00:01:23.070 itself now IntelliJ uses the doc strings of the built-in modules to produce the 18 00:01:23.070 --> 00:01:27.240 intellisense tooltips that appear when you're using Python built-in 19 00:01:27.240 --> 00:01:31.119 functions and classes but as the built-in themselves are actually written in 20 00:01:31.119 --> 00:01:37.189 C IntelliJ can't examine the real source built-ins.py is a stub provider so that you 21 00:01:37.189 --> 00:01:41.159 can checked that various declarations and we have talked about that before now its easy 22 00:01:41.159 --> 00:01:44.549 discussed this with built-in with built-ins modules on the screens so I add 23 00:01:44.549 --> 00:01:49.770 a call to the code down here on line 54 to do that so we can see what we are talking 24 00:01:49.770 --> 00:01:52.770 about so type... 25 00:01:54.720 --> 00:02:01.690 again we get that same warning here unexpected argument so we can command or 26 00:02:01.690 --> 00:02:07.620 control-click on album you get access to the documentation that way but also 27 00:02:07.620 --> 00:02:12.170 going back and closed it down or come down here again we click on Help 28 00:02:12.170 --> 00:02:16.810 commander or control click on Help we can see the definitions in the built-in.py 29 00:02:16.810 --> 00:02:21.290 you can see that there's a comment field next to it so that the 30 00:02:21.290 --> 00:02:25.060 real signatures are unknown and has been restored from the doc string but the 31 00:02:25.060 --> 00:02:28.930 doc string doesn't list the functions arguments as a result that's the reason 32 00:02:28.930 --> 00:02:32.810 why IntelliJ doesn't know that it can take a parameter and to give the warning 33 00:02:32.810 --> 00:02:39.550 as such so close it down and go back to song.py and specifically we'll fix this 34 00:02:39.550 --> 00:02:44.500 error with the album_name so I'm going to change that to what it should 35 00:02:44.500 --> 00:02:48.320 have been called with name and we should find that error disappears because of course name 36 00:02:48.320 --> 00:02:50.630 is an attribute defined in 37 00:02:50.630 --> 00:02:55.560 our init method you can see the error then goes away and also delete this help album which 38 00:02:55.560 --> 00:03:00.180 we no longer need and I what will do is instead will start typing the new 39 00:03:00.180 --> 00:03:02.970 class so lets type the artist class 40 00:03:02.970 --> 00:03:15.730 out so...and I'm going to make a space again so we can see what we are doing here so... 41 00:03:15.730 --> 00:03:19.720 .... 42 00:03:24.680 --> 00:03:46.650 .... 43 00:03:46.650 --> 00:04:19.789 ..... 44 00:04:19.789 --> 00:04:31.520 ....ok we also want to document the method so.... 45 00:04:31.520 --> 00:04:34.520 ..... 46 00:04:35.689 --> 00:05:18.649 ..... 47 00:05:18.649 --> 00:05:48.800 .... 48 00:05:48.800 --> 00:06:03.869 ...again this is a good idea to put that type of documentation in if 49 00:06:03.869 --> 00:06:09.169 that is the case remember when you do make the change to go back and revise 50 00:06:09.169 --> 00:06:19.569 the documentation so all we are doing here is..... 51 00:06:19.569 --> 00:06:22.880 so theirs not really any checking their.... 52 00:06:22.880 --> 00:06:29.320 so the artist class has got 2 data attributes the string holding the artist's 53 00:06:29.320 --> 00:06:34.480 name and a list containing the album objects and its a standard way to organize your 54 00:06:34.480 --> 00:06:37.700 record collection now with the albums by particular group stored together 55 00:06:37.700 --> 00:06:42.610 compilation albums or the songs by various artists do complicate things in 56 00:06:42.610 --> 00:06:46.340 this design attempts to deal with that by allowing an artist to be specified 57 00:06:46.340 --> 00:06:51.090 for each song now the major problem with this design currently is that an artist 58 00:06:51.090 --> 00:06:56.150 object will have a reference to an album and that album object will also have a 59 00:06:56.150 --> 00:06:59.990 reference to the artist now the problems that that can cause are to do with 60 00:06:59.990 --> 00:07:04.500 garbage collection so when objects are no longer used in your Python code they 61 00:07:04.500 --> 00:07:09.810 still take up memory until they're ultimately destroyed now many more modern 62 00:07:09.810 --> 00:07:13.920 programming languages deal with this by a system known as garbage collection 63 00:07:13.920 --> 00:07:18.570 and that means that the runtime system keeps track of variables and reclaims their 64 00:07:18.570 --> 00:07:23.170 memory when they are no longer being used in the program anymore and that generally means even 65 00:07:23.170 --> 00:07:26.820 when they go out of scope or when there is no longer anything else referring to them 66 00:07:26.820 --> 00:07:32.910 as an example now if where to create an album object for say adells 25 67 00:07:32.910 --> 00:07:38.250 it would have a adell as its artist attribute however the adellt artist object would have 25 68 00:07:38.250 --> 00:07:42.790 in its list of albums so when the program is no longer using these the 69 00:07:42.790 --> 00:07:45.170 garbage collector might see that there's still a reference to both 70 00:07:45.170 --> 00:07:49.460 objects each from the other one and then ultimately not reclaim the memory 71 00:07:49.460 --> 00:07:54.490 for either so you can see how would then would stall both of those entries sort of 72 00:07:54.490 --> 00:07:59.840 permanently well until your program finishes and won't claim 73 00:07:59.840 --> 00:08:03.840 the amount of memory space with that said the Python 3 garbage collector is quite 74 00:08:03.840 --> 00:08:09.000 advanced and can actually cope quite well with these situations but circular 75 00:08:09.000 --> 00:08:14.820 object references like the one like this that I just mentioned are still best avoided and 76 00:08:14.820 --> 00:08:18.390 another problem with circular references like this is that it can seriously 77 00:08:18.390 --> 00:08:23.250 complicates saving the objects to file or to a database so sticking with the 78 00:08:23.250 --> 00:08:27.830 adell for a moment when we try to write a adelts artist object then we will go through all the 79 00:08:27.830 --> 00:08:32.060 attributes and save them into disk when we get to the album's object the program 80 00:08:32.060 --> 00:08:34.810 will go through the album attributes and save them to disk 81 00:08:34.810 --> 00:08:38.219 in the process it would find an artist attribute that would then need to be 82 00:08:38.219 --> 00:08:42.000 saved so it will go through all the attributes and save them to disk in the 83 00:08:42.000 --> 00:08:45.750 process finding a collection of albums each containing a reference to an artist 84 00:08:45.750 --> 00:08:51.670 object that contains a collection of objects and so on so Python pickle module 85 00:08:51.670 --> 00:08:56.480 can often cope with this type of listing but there are limits and it 86 00:08:56.480 --> 00:09:00.960 can also get quite confused he can get quite confused and I think you can too as the 87 00:09:00.960 --> 00:09:06.290 program in this scenario and in actual fact I have made it even worse here and 88 00:09:06.290 --> 00:09:12.490 I've done that by also storing the artist as an attribute of each song in the album's tracklist so lets just open up 89 00:09:12.490 --> 00:09:18.029 an image to see this in more detail so let's just have a look at the class 90 00:09:18.029 --> 00:09:23.560 structure for what we've come up with you can see the diagram on the screen so this is a 91 00:09:23.560 --> 00:09:27.200 little bit complicated and there's really no good reason for storing the 92 00:09:27.200 --> 00:09:33.240 artist object in the song class for example the artists name would be enough 93 00:09:33.240 --> 00:09:36.440 to allow the actual artist object to be retrieved 94 00:09:37.310 --> 00:09:42.600 if more details were required so we are gonna take a look at that later and just to be clear 95 00:09:42.600 --> 00:09:46.030 I'm not saying that you should never allow circular references in your code 96 00:09:46.030 --> 00:09:51.450 but if you do allow them then it should be for you know a really good reason with 97 00:09:51.450 --> 00:09:56.150 that said you should also be aware of what's going on and also of the potential 98 00:09:56.150 --> 00:10:01.040 problems that may arise as a result of using them so we're going to remove the 99 00:10:01.040 --> 00:10:07.550 circular references a little later but we are gonna leave them in for now so that we can see the program does work as 100 00:10:07.550 --> 00:10:13.130 its currently set up so we are going to go back to the code and now that our classes are 101 00:10:13.130 --> 00:10:17.540 defined let's move on and start doing something with them know rather than 102 00:10:17.540 --> 00:10:22.850 doing loads of typing and also because using classes to pass data is a very good 103 00:10:22.850 --> 00:10:27.959 way to do it I'm gonna read in the songs information from a text file now we've got 104 00:10:27.959 --> 00:10:31.440 a file albums.zip that can be downloaded from the Resources section 105 00:10:31.440 --> 00:10:36.880 of this video so download that file then extract the file and then copy that file 106 00:10:36.880 --> 00:10:40.020 to the same directory as your Python project 107 00:10:40.020 --> 00:10:44.330 file in IntelliJ and again you can do that too easily determine where you are by just 108 00:10:44.330 --> 00:10:46.290 right clicking the project here 109 00:10:46.290 --> 00:10:51.120 and coming down to reveal in finder which may be show files or something like that on a 110 00:10:51.120 --> 00:10:56.250 different platform click on that and it takes us into the folder so I'm gonna put the 111 00:10:56.250 --> 00:11:02.399 actual files in that folder there where my other py files are and I'm just gonna navigate 112 00:11:02.399 --> 00:11:04.410 to the file location 113 00:11:04.410 --> 00:11:09.579 where I've already downloaded the files the album.zip and unzip and copy it in their 114 00:11:09.579 --> 00:11:12.899 so I'm gonna go to that folder to my downloads folder 115 00:11:14.449 --> 00:11:20.560 ok I got albums.zip their so I'm going to unzip that theirs the albums.txt file that we 116 00:11:20.560 --> 00:11:26.410 are going to import I'm going to take a copy of that go back to the path where my project files are and 117 00:11:26.410 --> 00:11:30.230 pasted that in there and then when I go back to the code in IntelliJ 118 00:11:30.940 --> 00:11:37.560 we got albums.txt just appeared so the file if we have a look at it you can see 119 00:11:37.560 --> 00:11:43.579 it's a tab separate list of songs with each song records starting on a new line now 120 00:11:43.579 --> 00:11:48.690 a record here consists of the artists name the album name the year it was released as 121 00:11:48.690 --> 00:11:54.269 well as the song title now Python will make light work of parsing this kind of data all we 122 00:11:54.269 --> 00:11:58.970 really have to do is to split each line at the tab character and convert the result to a 123 00:11:58.970 --> 00:12:03.540 tuple and it's also necessary to remove the end of line marker from each 124 00:12:03.540 --> 00:12:07.750 line and fortunately there is again trivial to do in Python so let's 125 00:12:07.750 --> 00:12:12.449 create a function to load this data up and call it only if the program is executed 126 00:12:12.449 --> 00:12:19.149 as a script so going back to our code again I want to close this text file so here in our 127 00:12:19.149 --> 00:12:23.880 artists class we are not going to put in the artist class we are going to start typing it as 128 00:12:23.880 --> 00:12:33.980 a separate function outside of the class so.... 129 00:12:33.980 --> 00:12:36.399 ..... 130 00:12:36.399 --> 00:12:42.100 .... 131 00:12:50.259 --> 00:13:04.620 ..... 132 00:13:04.620 --> 00:13:13.980 ... 133 00:13:13.980 --> 00:13:18.350 .... 134 00:13:21.480 --> 00:13:43.449 .... 135 00:13:44.129 --> 00:13:50.509 ..... 136 00:13:50.509 --> 00:13:58.319 ...so that should give us our 4 fields and as you can see Python makes light work of something that 137 00:13:58.319 --> 00:14:02.500 would take a lot more code in other languages..... 138 00:14:02.500 --> 00:14:08.559 ... 139 00:14:08.559 --> 00:14:22.920 ....and that's our method so lets go back 140 00:14:22.920 --> 00:14:27.720 and confirm this works again we are only running this 141 00:14:28.559 --> 00:14:34.240 if the programs executed as scripts so we are going to do a test here so... 142 00:14:34.240 --> 00:14:43.879 .... 143 00:14:43.879 --> 00:14:50.629 ...alright lets try running the program 144 00:14:50.629 --> 00:14:54.050 and we should see that its displays the details for all the songs from the 145 00:14:54.640 --> 00:15:01.550 text file so run song and it seems to have worked ok we've got a list of the 146 00:15:01.550 --> 00:15:06.990 artists field the album the year as well as the song title itself so that's 147 00:15:06.990 --> 00:15:13.500 good that is working well.....so you can 148 00:15:13.500 --> 00:15:20.200 see there or you could see their that the fields variables seem to be getting the correct values ok so we got 149 00:15:20.200 --> 00:15:23.200 that working.... 150 00:15:25.220 --> 00:15:29.030 so now we got this working I'm gonna finish the video here in the next video we're going to 151 00:15:29.030 --> 00:15:34.500 move on and enhance a little bit more so if we are gonna start putting the data into the classes 152 00:15:34.500 --> 00:15:37.950 following naturally from the data so in other words as each rows are read 153 00:15:38.550 --> 00:15:42.160 we are gonna create a song object then add it to the album and when a new album is 154 00:15:42.160 --> 00:15:48.250 found in the data the current album is going to be store in the artist album list and a new album objects is going to be created 155 00:15:48.250 --> 00:15:51.510 with that current rows details so lets work on that in the next video