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

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds 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 the default subtitles language 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 see our video player troubleshooting guide to resolve the issue.

A Better Pizza Interface With Class Methods

Give Feedback

After building the Pizza class, it’s time to extend it using @classmethods. In this lesson you’ll add class methods for different pizza types, to that you can create your favorite pizza without remembering the ingredients!

00:00 Okay. So, I wanted to make it a little bit easier for us to create new Pizza objects without having to remember all of these ingredients. A really good way to structure this, in my opinion, is to actually use class methods to have different factory functions for the different types of pizza you can create. I’m going to show you how this works in a minute now.

00:20 So, what I’m going to do here is I’m going to define a .margherita() class method here, and then that’s just going to create a new instance of the class…

00:32 and let me just type that out here. What I’m doing here is whenever this .margherita() method is called—and we can call it on just a Pizza class, we don’t actually need a real Pizza instance—I’m just going to create an instance of a Pizza or whatever the class is named.

00:52 Like, the nice thing here is that I don’t have to refer to the name up here, so I can keep that name just in one place and whenever I update it I don’t have to worry about changing the rest of the code, but it’s just going to call this .__init__() method, here, and it’s going to create a new Pizza with these ingredients.

01:12 And so, this is a really maintainable way to do these factory functions. I could also have a .prosciutto()I didn’t actually look the spelling up for this, all right?

01:25 So, if any Italians are watching this…

01:30 then let me know if I screwed this up!

01:34 So here, we actually want a cheese—I guess it would be 'mozzarella', right, and not 'cheese', but whatever—it’s a kind of cheese. Anyway, this isn’t about cheese—this is about Python. So, okay. I’m creating a different kind of pizza here, and now when I finish defining this class, I can actually say, “Hey, I want a Margherita,” and that returns a new Pizza object, right?

02:03 I could have also called this .make_margherita() or .new_margherita(), or something like that, right? Just to kind of have a better naming scheme.

02:11 But the same thing is going to work with the .prosciutto(). And

02:19 I feel like this is a really good use for these class methods. If you have classes with complicated constructors that take a lot of arguments and you want to provide a simplified interface for your users, then I think using a class method in this fashion can be really beneficial, and it’s just going to make the API a little bit easier for people to work with.

02:40 So, this is one example of where I would use a static method. I mean, of course, you could always argue that maybe this should be a separate function, yada yada yada, but I think in some cases this could really work well if you structure your classes that way.

seyi bello on Aug. 5, 2019

A static method can also be used to create factory functions. What is the difference between the 2 below:

class Pizza:

    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients})'

    @classmethod
    def margherita(cls):
        return cls(['cheese', 'tomatoes'])

    @classmethod
    def prosciutto(cls):
        return cls(['cheese', 'tomatoes', 'ham', 'mushrooms'])
class Pizza:

    def __init__(self, ingredients):
        self.ingredients = ingredients

    def __repr__(self):
        return f'Pizza({self.ingredients})'

    @staticmethod
    def margherita():
        return Pizza(['cheese', 'tomatoes'])

    @staticmethod
    def prosciutto():
        return Pizza(['cheese', 'tomatoes', 'ham', 'mushrooms'])

mdroberts on Nov. 15, 2019

Why do you refer to the Pizza factory methods as “Static method” sometimes and “class method” at other times? They are not synonymous as there are “static methods” distinct from “class methods”?

Dan Bader RP Team on Nov. 15, 2019

If you use a staticmethod instead of a classmethod you’ll need to spell out the class name explicitly in the method body:

@staticmethod
def margherita():
    return Pizza(['cheese', 'tomatoes'])

This means if you ever rename the class to something else (e.g. PizzaFlatBread) these methods will break, because Pizza is now undefined.

With a classmethod you can avoid this issue because you’ll get a reference to the class you can use instead of referring to the class name explicitly:

@classmethod
def margherita(cls):
    return cls(['cheese', 'tomatoes'])

In the example above, check out how I’m using cls(...) to create the instance instead of calling Pizza(...) directly :)

RobyB on Feb. 5, 2021

Italian watching here 😂😂 Don’t worry about the pronunciation of Prosciutto 😀 the best thing you can do is putting always mozzarella and not other kind of cheese 😀 Anyway, good and clean tutorial.

Become a Member to join the conversation.