The itertools, pathlib, and calendar Modules
00:00 In the previous lesson, I showed you how error messages have improved in Python 3.12. In this lesson, I’m going to cover changes to three different standard library modules.
00:10
Python 3.12 sees the addition of a new function to the itertools
module called batched()
. It takes an iterable and returns a series of groups.
00:21 Say you have a list of things you want to show on a page and want to group it into columns. This is a convenient way of doing just that. Back to the REPL, and let’s check it out.
00:33
Before hitting the 3.12 world, a quick detour. There’s a great third-party library out there called more-itertools
, and it has a function that is quite similar to batched()
.
00:45
It’s called chunked()
. Let me create some data. Now I can iterate over the string.
01:01
Strings as iterables return a letter at a time. Instead, if I use chunked()
,
01:14 I get a series of lists with four items at a time. The columns in my rows I mentioned before. Let’s see how this has been added to the standard library in Python 3.12.
01:28
Importing … build my string again … and this time, I’ll use batched()
instead of chunked()
.
01:47
The only difference is you get tuples instead of lists. I’ve used chunked()
a bunch when laying out cards on a webpage, so in the future, this will mean one less third-party library dependency for me.
02:02
I really like the pathlib
module. It feels far more Pythonic than its predecessor. I’m not sure why, but I only discovered it in the last couple years, but evidently it’s been around since Python 3.4.
02:14
If you’re not familiar with it, it covers all of what os.path
does along with some of what the os
module does, but in a more object-oriented fashion.
02:24
A common activity when dealing with a directory is to loop over its contents. Prior to 3.12, Path
did have a way of iterating over a directory, but it didn’t handle subdirectories. To do so, you’d write a recursive function to descend into any subdirectories found, and then calling the iteration method once more.
02:43
This always seemed like a shortcoming, especially seeing as the os
module had a .walk()
method. Well, so now 3.12 has one as well.
02:53
It does all that subdirectory iteration for you, allowing you to iterate over an entire tree. Off to the REPL once more, this time to take a walk. As I’m going to be walking a directory structure, I needed a directory structure. I’m showing it here using the tree
utility.
03:12 It comes with some Unix variations, but not with all, but it’s a good tool. If you don’t have it, it’s worth downloading. As you can see, it descends a directory and prints out a tree version of its contents.
03:24
For the case of this exercise, this is what I’m going to be walking. To take a walk, first I need a path. When you work with pathlib
, you create objects based on a file or a directory.
03:39
And that would be the Path
object for the musicians/
subdirectory. Let me stick this in a variable so I can do stuff with it. Now I’m going to walk the path. The .walk()
method returns a series of tuples.
03:57
Each tuple contains the name of the directory, the list of subdirectories inside of it, and the list of files inside of it. Build that into a for
loop …
04:28
and there you can see what .walk()
returns. From that tree, I have three directories: the root musicians/
folder, one for trumpet/
, and one for vocal/
.
04:38
Each row consists of a tuple, and that tuple contains the contents. For example, the musicians
tuple has a list of directories, which is the trumpet/
and vocal/
subdirectories, and the single readme
file inside of it.
04:52
.walk()
then descends into trumpet/
and then descends into vocal/
as well. The default processing order is top-down, but you can do bottom-up as well.
05:03
You control this by adding the top_down
argument.
05:12
The default is True
, so this will do the exact same thing you saw before. By changing it to false,
05:32 I get the output the other way around. To see a practical example, here’s something I cribbed from the docs.
06:17
This walks the directory, uses the .stat()
method on each one of the files in the directory, and then sums up their size totals, and then counts how many non-files there are in the directory itself. Let me hit Enter … and this is the output for my dummy musicians/
structure.
06:37
It’s mostly placeholder files, as you can see by the tiny byte totals. The last little addition is to the calendar
module. Did you know there was a calendar
module?
06:50 It even has a callable feature where you can print a calendar from the command line. I chopped this one at March to fit it on the screen, but all twelve months would normally be there.
07:00
There are two small additions to calendar
in 3.12. Both are Enum
classes, one for the months of the year and the other for the days of the week.
07:10
Back into the REPL I go. I’m going to import calendar
… and there’s the new Month
enum. If I cast it to a list, you can see it has an entry for each month in the year.
07:31
The other enum is Day
. And it has the names of the days of the week. Thor would be proud. All right, let’s do something with this. I’m going to grab a date.
07:53
3.12’s release date is as good as any to play with. And the .weekday()
method on the date
object returns a number, and this number is kind of the reason for adding the enums.
08:08
Just what does 0
mean? Well, I can create an instance of Day
with it and find out.
08:23
0
means Monday. Enums have members that allow you to get at the name, the numeric value, and the Enum
instance itself. I’ll demonstrate the difference with a quick sales report.
08:40
These are my sales numbers for twelve months. Now I can iterate over the Month
enum …
09:00
and print the object’s value, name, and use it to index the sales loop. Note the -1
there in the third term. I’m converting month 1
to 0
to get the first thing in my list.
09:13 And the results … there you go, one enum-based sales report. I hope those numbers are in millions. It wouldn’t be a Python release without some additions to the typing mechanism.
Become a Member to join the conversation.