1 00:00:00,000 --> 00:00:04,500 Okay. When we talk about the word 'package', and what I'm saying here 2 00:00:04,500 --> 00:00:06,500 is a package, 3 00:00:06,500 --> 00:00:07,500 it's a Python package. 4 00:00:07,820 --> 00:00:11,540 And really, all a Python package is, is a collection of modules, 5 00:00:11,800 --> 00:00:13,420 just a collection of Python files. 6 00:00:13,420 --> 00:00:14,900 Really, that's all it is. 7 00:00:14,960 --> 00:00:18,130 It might have some non Python files in there, but really, 8 00:00:18,130 --> 00:00:20,100 you're just looking for the Python files. 9 00:00:20,100 --> 00:00:24,310 So usually packages are put into their own folders, and 10 00:00:24,320 --> 00:00:26,560 and they use many files that relate to each other. 11 00:00:26,570 --> 00:00:29,660 So what I'm going to do, is I'm going to open up my Desktop 12 00:00:29,670 --> 00:00:33,229 entirely, and create a new file in here. 13 00:00:33,470 --> 00:00:34,850 So I'm on my Desktop. 14 00:00:34,850 --> 00:00:37,900 I have files that we've seen before throughout the rest of this course. 15 00:00:37,900 --> 00:00:42,600 I'm going to go ahead and create a new folder in here called 'MyPackage'. 16 00:00:43,100 --> 00:00:46,600 Now, we need to tell Python that this is not just a regular 17 00:00:46,600 --> 00:00:48,840 folder, and that this is actually supposed to be a package. So, 18 00:00:48,840 --> 00:00:51,600 what we do is we create a new file in here. 19 00:00:51,600 --> 00:00:55,900 So I'm going to create a new file called '__init__.py', 20 00:00:56,900 --> 00:01:00,000 and this file is going to have absolutely nothing in it. 21 00:01:00,040 --> 00:01:02,050 This simply just tells Python, 22 00:01:02,050 --> 00:01:06,300 "Hey, you know, when you go to look into the MyPackage folder 23 00:01:06,300 --> 00:01:10,700 and there's an '__init__.py' in there, just treat it as a package, please. 24 00:01:10,780 --> 00:01:14,020 So once that's created, you don't have to do anything with it. 25 00:01:14,020 --> 00:01:17,400 Now, I'm going to create a new file in here 26 00:01:18,400 --> 00:01:25,400 called 'my_functions.py', and give it a name up here, 27 00:01:25,400 --> 00:01:28,700 'my_functions.py', and by the way, this is not necessary. 28 00:01:28,710 --> 00:01:29,780 I just like seeing that. 29 00:01:29,780 --> 00:01:33,900 It also helps viewers see which file I'm in a little easier as well. 30 00:01:33,900 --> 00:01:36,590 I know it's here and here, but sometimes that's not totally 31 00:01:36,600 --> 00:01:39,890 apparent. I'm actually one of those people that even though 32 00:01:39,900 --> 00:01:42,590 it is right there, sometimes my eyes just don't see it, 33 00:01:42,600 --> 00:01:43,800 so I like to put it there as well. 34 00:01:44,500 --> 00:01:46,600 And you never know what other text editors people are going to 35 00:01:46,660 --> 00:01:48,180 be using when they download these files, so 36 00:01:48,190 --> 00:01:52,080 anyways, that is my explanation of why I write that up 37 00:01:52,090 --> 00:01:55,740 there. And now in here, I'm going to create a new function 38 00:01:55,890 --> 00:01:59,180 completely, and I'm going to call it 'a_new_function()', 39 00:01:59,600 --> 00:02:03,560 and all this is going to do is say, 'print( 40 00:02:03,780 --> 00:02:08,650 "This is from my_functions.py")'. That's it. 41 00:02:08,660 --> 00:02:10,240 I'll make that a tad smaller, too. 42 00:02:10,900 --> 00:02:15,610 Now, beside the 'MyPackage' directory, I'm going to create 43 00:02:15,610 --> 00:02:16,900 a new file in here. 44 00:02:16,900 --> 00:02:20,000 So I'm just going to copy this over, and I'm going to call 45 00:02:20,000 --> 00:02:22,500 this 'package_program.py'. 46 00:02:22,500 --> 00:02:27,000 Delete all that. 'package_program.py'. 47 00:02:27,800 --> 00:02:32,310 And so here I've got 'package_program.py', and it's living 48 00:02:32,310 --> 00:02:34,200 beside the folder called 'MyPackage'. 49 00:02:34,900 --> 00:02:41,000 Now, what I can do, is say 'from MyPackage.my_functions', 50 00:02:41,000 --> 00:02:44,000 and you can see that VS Code is actually trying to autofill that for me, 51 00:02:44,400 --> 00:02:47,300 'import', and what am I trying to import from here? 52 00:02:47,300 --> 00:02:49,800 I can import a function called 'a_new_function'. 53 00:02:50,000 --> 00:02:51,700 Let's go ahead and import that. 54 00:02:52,400 --> 00:02:55,700 And let's simply run that as a function. 55 00:02:55,700 --> 00:02:57,900 [no audio] 56 00:02:57,900 --> 00:03:02,100 So I'm in my Desktop here, and we can see the files that I have. 57 00:03:02,100 --> 00:03:05,200 And I've got 'MyPackage', 58 00:03:05,200 --> 00:03:07,300 that's a folder; and 'package_program', 59 00:03:07,300 --> 00:03:08,800 that's the file that we're using right now. So, 60 00:03:08,810 --> 00:03:14,380 'python package_program.py', and it says, "This is from 61 00:03:14,410 --> 00:03:16,000 my_functions.py'. 62 00:03:16,000 --> 00:03:19,800 And so really, all we've done here is very similar to what 63 00:03:19,800 --> 00:03:21,000 we did with a module, 64 00:03:21,080 --> 00:03:24,170 but instead of just being in another file, we said it's also 65 00:03:24,180 --> 00:03:27,050 in another folder, and we can do this on and on and on. 66 00:03:27,060 --> 00:03:30,050 So if we wanted to, we could create a subfolder in 'MyPackage', 67 00:03:30,700 --> 00:03:34,100 create a new folder, call it 'MySubFolder'. 68 00:03:34,100 --> 00:03:36,600 [no audio] 69 00:03:36,600 --> 00:03:42,400 In here let's go ahead and create a new file, '__init__.py', 70 00:03:42,400 --> 00:03:47,800 and let's create a new one in here called, a new file called 71 00:03:48,000 --> 00:03:50,900 'subfolder_functions.py', 72 00:03:51,900 --> 00:03:53,500 and in here we can create 73 00:03:53,500 --> 00:03:55,900 [no audio] 74 00:03:55,900 --> 00:03:59,000 a variable. So let's create a variable, sort of like a constant, 75 00:03:59,030 --> 00:04:01,340 and in Python, we don't actually have constants, 76 00:04:01,350 --> 00:04:03,740 but what we do have is a naming convention. 77 00:04:03,750 --> 00:04:07,370 So instead of saying a variable name is like, 'name =', 78 00:04:07,380 --> 00:04:11,620 something, when we have a variable that we don't want to change 79 00:04:11,620 --> 00:04:15,600 we usually use uppercase, and that tells us that it's supposed to be a constant. 80 00:04:16,100 --> 00:04:20,000 So I could say 'COURSE = "Python for Everybody". 81 00:04:20,399 --> 00:04:28,500 And in here I can have a function called 'which_course_is_this', 82 00:04:28,500 --> 00:04:32,000 and due to scoping, we know we have access to this, 83 00:04:32,000 --> 00:04:33,800 so we can just simply say, 'print( 84 00:04:33,800 --> 00:04:36,300 "The course is" 85 00:04:36,300 --> 00:04:38,300 [no audio] 86 00:04:38,300 --> 00:04:42,500 COURSE)'. So let's go back here, close that file 'package_program', 87 00:04:42,500 --> 00:04:50,200 let's also do 'from MyPackage.MySubFolder. 88 00:04:50,200 --> 00:04:55,000 subfolder_functions import', and I'll make that couple lines 89 00:04:55,000 --> 00:04:58,900 smaller. We want to import both 'COURSE', and this. 90 00:04:58,900 --> 00:05:00,800 We don't need to, we could actually just import this, and 91 00:05:00,800 --> 00:05:01,900 it'll work totally fine. 92 00:05:01,900 --> 00:05:04,900 But if we wanted to, we could import that variable as well. 93 00:05:04,900 --> 00:05:08,900 So let's go ahead and execute this. 94 00:05:08,900 --> 00:05:13,900 And so now we're importing a function that we made from 95 00:05:13,900 --> 00:05:15,900 'MyPackage.my_functions', 96 00:05:15,900 --> 00:05:21,500 and then we're also importing a function from a file called 97 00:05:21,550 --> 00:05:25,370 'subfolder_functions', a folder above that, 98 00:05:25,370 --> 00:05:28,700 the parent folder is 'MySubFolder', and the parent above 99 00:05:28,700 --> 00:05:30,000 that is 'MyPackage'. 100 00:05:31,300 --> 00:05:36,200 And when we run this, when we run this in Python, we'll see 101 00:05:36,200 --> 00:05:38,300 "This is from my_functions.py". 102 00:05:38,300 --> 00:05:41,900 And this one is, "The course is: Python for Everybody". 103 00:05:41,900 --> 00:05:44,500 And we actually don't have any 'print' statements in here whatsoever. 104 00:05:44,500 --> 00:05:48,400 And so we've now created what is effectively a package. 105 00:05:48,400 --> 00:05:51,500 Now to clarify how some of this is actually working, 106 00:05:51,680 --> 00:05:56,360 when you import from something you can say 'from MyPackage', 107 00:05:56,360 --> 00:05:57,600 and usually we name it 108 00:05:57,680 --> 00:06:00,470 whatever the regular package is called, it doesn't have to be 109 00:06:00,480 --> 00:06:01,730 uppercase or anything like that. 110 00:06:01,740 --> 00:06:06,440 Like we saw earlier that you could have 'from colorama import 111 00:06:06,800 --> 00:06:11,600 Fore', but the weird thing here is this '.' notation. 112 00:06:11,600 --> 00:06:15,950 So sort of what this is doing here is instead of for whatever 113 00:06:15,960 --> 00:06:18,740 reason, and I actually don't know this, but for whatever 114 00:06:18,740 --> 00:06:20,900 reason, we use dots instead of slashes. 115 00:06:20,920 --> 00:06:24,590 And so in Python, we can say 'from MyPackage' folder, 116 00:06:25,500 --> 00:06:27,900 look in 'MySubFolder' folder, 117 00:06:27,980 --> 00:06:32,760 and then the last one is likely to be a Python file, which 118 00:06:32,770 --> 00:06:34,050 you just automatically assume, 119 00:06:34,050 --> 00:06:35,800 so you don't have to write '.py', 120 00:06:36,800 --> 00:06:40,400 and instead we use this thing called '.' notation where folder 121 00:06:40,400 --> 00:06:43,200 name, folder name, file name, import your function. 122 00:06:43,220 --> 00:06:47,420 We could if we wanted to, do this a different way as well. 123 00:06:47,420 --> 00:06:54,100 We could say 'from MyPackage.MySubFolder import 124 00:06:55,100 --> 00:06:58,900 subfolder_functions', and then we could run 'subfolder_functions. 125 00:06:59,900 --> 00:07:00,800 which_course_is_this' 126 00:07:00,800 --> 00:07:04,300 And let's go ahead and execute this just to see that this is going to work. 127 00:07:04,310 --> 00:07:07,860 Now, I commented out both functions that we're running originally, 128 00:07:07,860 --> 00:07:09,700 so this one is not going to show up anymore. 129 00:07:09,700 --> 00:07:11,700 [no audio] 130 00:07:11,700 --> 00:07:17,200 And there it is. Just the one shows up, and we can even alias this if we 131 00:07:17,200 --> 00:07:18,900 want to. You might see this from time to time, because 132 00:07:18,900 --> 00:07:21,700 'subfolder_functions' is kind of a long name, 133 00:07:21,700 --> 00:07:25,600 so you might see something like this 'as', I don't know, 134 00:07:25,600 --> 00:07:27,800 'subfolder_functions', 'sff'. 135 00:07:28,020 --> 00:07:30,120 And then we can use that instead. 136 00:07:30,130 --> 00:07:33,810 And now this looks a lot like a class, doesn't it, where 137 00:07:33,810 --> 00:07:36,500 we have an object or a class name, 138 00:07:36,500 --> 00:07:38,100 and then we've got a method in it. 139 00:07:38,100 --> 00:07:43,100 And every now and then I mentioned that Python is, everything 140 00:07:43,100 --> 00:07:45,100 in Python is pretty much an object. 141 00:07:45,140 --> 00:07:46,700 Files are no different. 142 00:07:46,710 --> 00:07:49,720 And I do remember saying that. Files are no different in the 143 00:07:49,730 --> 00:07:52,700 sense that we imported this file, and now we have a function 144 00:07:52,700 --> 00:07:54,900 in here, and that's the method. 145 00:07:54,960 --> 00:07:57,840 Very interesting how they're very, very similar, isn't it? 146 00:07:57,900 --> 00:08:03,000 So just for funsies let's go ahead and run this, and it still works. 147 00:08:03,000 --> 00:08:04,400 [no audio]