[00:00] In this video, I will share with you five tips to better organize your Python code. These are not going to be life changing. They're not going to have to do with software design and software architecture. There are simple things that you can implement that make your code much more [00:13] readable and easier to navigate. With that said, let's get into tip number one. All right, so my tip number one is to use modules and packages. Now a module is an individual [00:33] Python file. A package is a directory containing multiple Python modules. This is the best way to organize your Python code whenever you're working on a relatively large project. You definitely want to utilize both of these things. Right now, I will give you a quick two-minute tutorial on [00:49] how they work. If you want to learn more and learn more about software design in particular, then check out my course programming expert.io. I'll leave a link to it in the description. You can use discount code Tim if you're interested. Regardless, let's have a look at this. [01:02] So here you can see that I have this physics package. And what makes it a package is the fact that I have this knit.py file inside of it. So whenever you want to make a package, you do a directory. You put some Python modules, whatever you want. You don't have to have any, but if you want some. [01:16] And then you put an underscore underscore knit underscore underscore dot pie. Now this is a special file. And I'll talk about how it works in a second. But this is what makes this folder here a package. Okay. So now that I've done that from main dot pie, I can come here and say import and then just [01:34] import the name of the directory itself. No, notice when I run the code here, there's no error. I'm able to import this successfully. And let's have a look at something cool here. When I go inside of a knit.py and I run the code or I have print hello world. Now when I come to [01:49] main dot pie and I run this, notice hello world prints out. Now I didn't print anything from here. I just imported the physics package. And what happens is whatever's inside of a knit.py, that's going to run exactly one time. The first time that this package is imported. So from my main [02:06] file, I import the package. And then whatever's inside of here runs exactly once. Now the power of this is that you can do some initialization code inside of your package. You also can import things [02:18] from a knit.py, which then allows main dot pie to import them without knowing what's inside of the package. So you'll see what I mean here. But I have this class. Let's actually go with forces. Okay. So I have this forces class. So what I can do is go to a knit.py. And I can say something like [02:34] from dot and then forces import and then forces. Okay. We'll continue to print hello world. And now what this allows me to do is from main dot pie. I can now say from physics import and I can [02:49] import forces. And the reason I can do that is because we imported here. Now if I remove this line. So let's actually remove it and try. When I run this, notice it says forces is not in the module fit or not in the package physics. Sorry. Can't find it. Okay. Let's clear that. Let's go back here. [03:05] Let's re import that. Now let's run and notice it prints out hello world. But now I can also use forces if I want. So I could say forces like this. And when I initialize it, I just print something out. So let's initialize it. Let's run. And then I get hello world and forces. So that is really the [03:21] power of modules and packages. You can put packages inside of other packages. And what I was doing here in a net.py something called a relative import where I am importing from the current package. That's what the single dot means. The the forces file. And then from the forces file. I'm importing [03:38] the forces class. Anyways, that is tip number one. Use modules and packages. Don't be afraid to separate your code out. If you have one large file containing multiple classes, multiple functions, all kinds of stuff that doesn't make sense to be in one place. Separate into multiple modules. [03:53] Separate it into multiple packages. And then write the appropriate import statements to bring everything into the file that you beat. All right. So tip number two, maybe slightly controversial. So let me know in the comments if you disagree with me. Of course, there's exceptions to everything [04:06] that I'm saying here. And this is going to be to place a single class in a single file. Again, there may be some exceptions. Some people may say do not do this. But for me, when I'm writing primarily object oriented style code in Python, I like to place each of my classes in an individual [04:23] file. So in this case, I have an angular momentum class. Obviously, it's a very simple example just for the video. And I've placed it in a file called angular underscore momentum. Now, another thing to note here, when you're naming files in Python, the convention is to do snake case. So snake case with [04:39] all lower case letters, you should not have any capitals in there. And if you want to have a space to an underscore, but when you're naming a class, you want to have this in Pascal case. So Pascal case means capital on the first word capital on all the other words, no spaces and no underscores. So [04:54] looks a little bit weird because this is different than the file name, but that's the convention in Python. That's what you are supposed to do according to pep eight. Anyways, that is what I'm saying for this tip, place each class in an individual file. I find this makes your code very organized, very [05:08] easy to find the different classes. And if you need to use a class from another class, then just import. Alright, that is tip number two. Alright, so for tip number three, which is to group related functionality together. I'm here on my organization's GitHub page. I'll leave it in the [05:23] description. If you want to contribute to open source projects, then please check this out. All of the stuff here is done by volunteers. I have not written a single line of code. And this is all organized and facilitated through my discord server, discord.gg slash TWT. I'll leave a link [05:38] to that in the description. We have like 33,000 members. So please join that if you want to be a part of this. And you can also ask some of the people who have set these repositories up. Hey, how did you structure the code? If you're curious about that. Anyways, I'm going to go to this API directory here. [05:51] I don't know what a lot of this stuff is because again, I've not written any of this code. It's all volunteers. But I'm just going to show you how they've kind of structured the different repositories. And you'll see how easy it is to navigate everything and how someone like me who again has really [06:04] never looked at this before can easily figure out where all of the different code is. So the tip was, as a reminder, group-related functionality together. So immediately when I'm looking here, I see a bunch of random files. These files are fine to just be in the main directory because they're [06:17] all kind of unrelated and since all these things are unrelated, they'll all be in the same place. So we're grouping the unrelated things together, which in turn groups related things together. Anyways, that we have utils, tests, docs, and then API. So immediately we have four packages or [06:33] four directories that are separating out the main things that we have in our application. So when I go to utils, I see that I get some utilities. Notice I have my knit.py. Inside of here, we're importing a few things and saying, all is equal to this. Another Python convention. I won't [06:48] really talk about that. Then if I come here to test, I have a bunch of different tests. I have my test utilities. So the utilities for the tests are in a separate, I guess you could call this a package, although it doesn't have the knit.py file, but that's fine. You could still kind of call the package. [07:04] Continuing, we have our docs. Documentation here. So we have an MD file, a markdown file, for how you actually run some of the different things here. Going back, we have API. Inside of API, we have models. We have services. We have versions. If I go to services, we have the different services. [07:20] If I go to versions, we have a version V1. So this is where I'm getting at. It's not super complicated. There's not a ton of stuff that you have to do. Just think logically about what stuff makes sense to be together and put it together. In this case, they thought we had API documentation tests and [07:35] utils. That was the main group of stuff. Okay, all the stuff related to that goes inside of the package. If there's more specific stuff within say the API within the docs, we make a new package or folder for that. And we are good to go. All right. So my next tip is a quick one. And this is to place all [07:51] of your utilities in a single place. So either a single file or a single package. Now there's a lot of times when you're writing kind of helper functions or functions that don't belong in a certain class or belong in a certain file. And you don't really know where to put them. For example, maybe you want to [08:07] convert a date from the date time object to a string or maybe you want to figure out the distance between two points. Whatever, there's some random kind of helper functions that again aren't easily classified into a class or a file or some part that already exists in your application. If that's [08:24] the case, what you want to do is create a utility package or a utility module if you only have say three or four functions that you're using and dump them all into there. Like I was saying before, when you have stuff that's not related together, all of the stuff that's not related, you should put [08:39] in one place because what relates it is the fact that it's not related to something else. I know that's a little bit backwards, but I just want to show you here in this code base. They have the utils package, right? And instead of utils, we have things related to permissions. These are going to be used in [08:53] multiple places. They don't make sense to be anywhere other than the permissions file, right? Same thing with response. We have stuff related to your response. We have a JSON response class time.py. Okay, this is doing stuff with time, snowflake time, whatever. I don't know exactly what's going on, [09:08] but the point is the way they've named this and organized it, it's very easy for me to go in and see where the utilities are being used. And that way, they're not clogging up different files. And if I want to add something or change something, I can do it all in one place in the utils package or utils file. [09:24] That was it for that tip. Let's move on to number five. All right. So my last tip for you here is to organize your import statements. Now, I don't know if they've done it exactly the way I'm going to recommend in this code base, but I can already see that they have this being done decently. And this becomes very [09:39] important when you have a ton of different imports and a large project. So you'll see a lot of Python files where you have like 20 imports, 30 imports. In this case, we have 11 imports. And it's just really nice and easy when you actually organize and sort the imports. So you can go in whatever style you [09:54] want. So long as you're consistent across your project, what I like to do is import all of my third party libraries first, which is actually what they've done here. So they're using fast API. So they take all their stuff from fast API, then from fake retis, then from AIO HTTP, then from logging, [10:11] although logging is actually a built-in module on Python. So I wouldn't put that exactly with all of this. And it was I like to go third party imports. Then I like to go built in imports. So something like OS, JSON, logging, stuff that you don't have to install this built into Python. Then I like to go [10:26] with my local files and my relative imports. So in this case, these are all local files that they've coded themselves, utils.response, API, config. And then lastly, I like to alphabetically order my imports, [10:39] although that can be a little bit challenging sometimes because you have to ask, how are you doing it alphabetically? Are you doing it by the name of the package, for example, the name of the module? Are you doing it by what you're importing? So that one's not as important. Anyways, this just makes [10:52] it really easy to quickly go in, locate the different things that you're importing. See if you need to change something and know what block you're going to add a future import to. So again, they haven't done exactly like I would do it, but this is pretty good. They have all of your third parties. Then they [11:06] have their built-ins. I would put this one line down just to have third parties built in and then I have all of my local imports or relative imports. So just to continue to test these guys and see if they've been consistent here, let's go into another file. And okay, so here I already notice a few inconsistencies. [11:22] So these are local files. Then we have another local file. Then we have our built-in, which is typing. Then we have our third party module. Then we have a local file. Then we have another local file. Now, maybe they've organized it in this way for some reason that I'm not familiar with or that I [11:37] just don't understand because again, I don't write this code. This is not my codebase to maintain. But what I would have done is swap it around. So it was in the order I said third party built-in and then your local files. However, again, there's always exceptions and you can always make debates. This is not [11:52] a strict rule. These are just tips that for me, I find helpful and will hopefully they helped you. With that said, I will wrap up the video here. If you guys enjoyed, make sure you leave a like, subscribe to the channel, check out programming expert if you want to learn more about this topic. [12:05] And I will see you in another YouTube video.