Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please refer to our video player troubleshooting guide for assistance.

Classes in the Standard Library

00:00 In the previous lesson, I showed you some more dunder methods and probably exhausted your eyes from all their rolling at my puns. In this lesson, I’ll show you some of the classes available to you in the Python standard library. Data classes were introduced in Python 3.7, and they’re a shortcut for creating the attributes on a class.

00:21 They’re kind of like a dictionary and a namedtuple got together and had a wonderful little love child. You create a data class by wrapping a class declaration with the @dataclass decorator. There are other ways as well if you dig into the docs, but I’m going to stick with this one.

00:37 In addition to allowing you to specify the names of attributes, you can indicate the type of the attribute in case you’re using type annotation tools. On top of all this, it is still a class, so you can add your own methods.

00:51 Now that Python 3.6 is no longer supported, it is safer to write code that assumes data classes exist. Increasingly, I’m writing a lot of my classes as data classes, so I don’t have to write the .__init__() boilerplate. Let’s go look at some.

01:08 First off, I need to import the decorator.

01:14 Then I use it to wrap a class definition,

01:21 yet another version of Point, and inside the class, I indicate the name and type of any attribute I want on the class.

01:33 If you’re using a more recent version of Python, you can even use the or-ed notation on the type. What the data class does for you is automatically implement a bunch of stuff. For free, you get a .__init__() that uses the same arguments in the same order as they’re declared, x and y in this case.

01:52 You also get an implementation of .__str__() and .__repr__(), and as it’s a class, you instantiate it like any other. Creating my point, naming it p, with x 3 and y 4.

02:08 There’s .x, and there’s .y, just like any good attribute. The dataclass module also has a utility function.

02:20 Using it on a dataclass object, it automatically turns it into a tuple using the order of the named attributes. See what I mean about the dictionary and namedtuple getting a little romantic?

02:34 Let me create another point. The dunder comparison methods are also implemented on a data class. p and q aren’t the same. p and p are.

02:48 Let me add another point.

02:53 And notice, the equality check isn’t checking if they’re the same object, but comparing the attribute values. p and r are different objects, but show as equal because they have x = 3 and y = 4.

03:11 An enum is a grouping of constants. Note that the iterable utility enumerate() existed in the language before enums were added, so don’t confuse the two concepts. And yes, you can enumerate an enumeration. Isn’t coding fun?

03:28 The idea of an enum is built into some programming languages. Python added it in 3.4, but instead of creating a new keyword, they used class magic, some very black meta class magic in fact, but you don’t need to know that to use them. To write an enum, you inherit from the Enum class, and kind of like a data class, you declare the constants as class members. And it’s still a class, so you can add methods and do other classy things.

03:59 Let’s go build an enum. Importing the base class …

04:07 extending Enum

04:13 and declaring class attributes for the constants in my enum. By convention, constants are written in all caps, so I’m sticking with that inside my enum declaration.

04:25 If you dig into the module, there are other ways to automatically assign values and shortcuts, but I’ll let you explore that on your own. With my enum class in hand, I of course can get at the attributes.

04:39 Note that that doesn’t just return 1. It’s its own thing. It actually is an enum object. That’s a bit weird, but you’ll see why in a second.

04:50 The purpose of an enum is grouping constants, so assigning a value appropriately gives an error. You can cast an enum to a list, and that list will contain all of its instances. You can construct the class with a value, and you’ll get back the corresponding enum object.

05:15 You can also look values up by name.

05:20 Remember when I said there was a reason you get back an enum object instead of just the value? Well, it’s because you can get at all the information associated with each part of the enum. Let me show you what I mean.

05:35 The .name attribute contains a string version of the enum member.

05:42 Well, .value contains the value. This allows you to go back and forth between the name, the value, and the enum object in your code as you need.

05:53 If I got a nickel for each time I said everything in Python is an object, I’d probably have enough for some candy in this course alone. Mmm, candy.

06:04 You may not have ever stopped and thought about what happens when you call a function, but in Python’s syntax, that parentheses on the end of the function are what is actually causing it to be called. But as everything is an object, even functions, using those parentheses to call something can be applied to an object as well. And in case you might have guessed, yep, there’s a dunder method for that.

06:29 When you stick parentheses on the end of an object, you’re calling it, and Python invokes the .__call__() method for you. A neat little aspect of this is many of those things you thought were functions are not. All the conversion calls? Yep, not functions.

06:45 They’re classes that have implemented .__call__(). In part one of this course, I spoke about using class methods for factories. These are essentially doing the same thing using that .__call__() method.

06:57 Same goes for iteration mechanisms like range() and enumerate(). In fact, over half the built-in so-called functions aren’t actually functions.

07:09 I hope you’re with me and not feeling dunder the weather. Told you I can do this all day. Next up, let’s be lazy and partially implement some classes, letting someone else finish the job for us.

Become a Member to join the conversation.