Locked learning resources

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

Unlock This Lesson

Locked learning resources

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

Unlock This Lesson

More Pizza and When to Use Static Methods

Now that you have learned when to use class methods, the question arises when to use static methods. The current lesson shows you an example, where you could make use of a @staticmethod. Furthermore, the code used in this lesson is provided below, so that you can copy and paste it to try it out yourself.

Python
>>> import math
>>> 
>>> class Pizza:
...     def __init__(self, radius, ingredients):
...         self.ingredients = ingredients
...         self.radius = radius
...
...     def __repr__(self):
...         return f"Pizza({self.ingredients})"
...
...     def area(self):
...         return self._circle_area(self.radius)
...
...     @staticmethod
...     def _circle_area(r):
...         return r ** 2 * math.pi
...
>>> 
>>> Pizza(4.5, ["cheese"])
Pizza(['cheese'])
>>> 
>>> Pizza(4.5, ["cheese"]).area()
63.61725123519331

00:00 Up next, when to use static methods. It’s a little bit hard to come up with a really simple example here, but you know, I’m going to keep stretching the pizza thing here. So, okay. This is what I came up with. Basically, a static method doesn’t have access to the class or the object instance at all, all right? And now, that’s a pretty big limitation, but it’s also a really good signal to show that a particular method is really independent from everything else around it. So for example, if I flag this as a static method, it’s pretty clear that this method, it’s probably not going to change the object or the class in any way,

00:46 because it’s not really meant to have access to it. I mean, sure, you know, you could probably work around that and it could kind of work with a global variable, but in general, it’s a pretty good hint that this is a self-contained method, which has all kinds of benefits for later testing this thing and just kind of understanding the limitations of this method.

01:04 And so in some cases, it can really be helpful to make your code easier to maintain in the future, because you’re really communicating this intent where someone else reading this code can pretty clearly understand that in this case, our little ._circle_area() function here—it’s not going to modify the state of this object itself.

01:22 So let me walk you through this example real quick. So basically, what I’ve added here—well, I kind of changed the constructor around a bit, so now we’ve got a radius argument here for the pizza as well.

01:33 I forgot to update the .__repr__(), but you know, it doesn’t really matter for now. And then I added this .area() function. And, well, I could have just calculated the area of the pizza directly in here, but I wanted to have a static method in there.

01:46 And so basically, what I did there instead of calculating the area directly with an expression here, I’m just offloading that to the ._circle_area() function, and then the ._circle_area() function just takes an r, which is the radius, and uses the classic r ^ 2 * pi formula to calculate the circle area. So, you know, this is honestly kind of a simplistic example, and you usually wouldn’t implement it like that, but it goes to show the concept.

02:15 And now what happens here is I can instantiate a Pizza. So for example, this is a really sad pizza with like 4.5well, we don’t have a unit on that—let’s say meters. A giant pizza, cheese only.

02:31 And we’re going to create this object, this Pizza object, and then we’re going to call the .area() function on it, and it’s going to give us this result.

02:38 So, the way this is calculated is that .area() actually forks off all that work to the ._circle_area() function, and now the ._circle_area() function is actually completely independent, and I also used a single underscore (_) to mark it as not part of the public API of this class, but kind of an internal implementation detail. But nevertheless, now the cool thing is that we have this ._circle_area() function that is completely independent from the rest of the object, and it can’t actually modify the object’s state.

03:15 This is a pretty good hint for someone else reading the code and it also simplifies testing because when I write my tests for this, then I don’t have to worry about instantiating a Pizza object, making sure it doesn’t get modified, because the ._circle_area() helper—it can’t do that. Right?

03:34 And so I occasionally use static methods to communicate that intent and to keep my helper functions nice and clean and make sure that they’re not modifying the object’s state all over the place.

Avatar image for prashant23

prashant23 on July 9, 2019

Thanks for the nice tutorial. So,the static method can be considered to write certain helper functions?

Avatar image for EKELENNOROM

EKELENNOROM on July 13, 2019

The code doesn’t work for python 3.6 and 3.7

Avatar image for Dan Bader

Dan Bader RP Team on July 15, 2019

@EKELENNOROM: What’s the error message you’re seeing? Works just fine here on my end (3.6 and 3.7), see below:

→ bpython
bpython version 0.18 on top of Python 3.7.3 /Users/dbader/.pyenv/versions/3.7.3/bin/python3.7
>>> import math
>>>
>>> class Pizza:
...     def __init__(self, radius, ingredients):
...         self.ingredients = ingredients
...         self.radius = radius
...     def __repr__(self):
...         return f"Pizza({self.ingredients})"
...     def area(self):
...         return self._circle_area(self.radius)
...     @staticmethod
...     def _circle_area(r):
...         return r ** 2 * math.pi
...
>>>
>>> Pizza(4.5, ["cheese"])
Pizza(['cheese'])
>>>
>>> Pizza(4.5, ["cheese"]).area()
63.61725123519331
Avatar image for Azian

Azian on July 31, 2019

The code runs fine for me on Python 3.7.4.

Avatar image for Zarata

Zarata on April 20, 2020

Maybe “Pizza” somewhat obscures this one. “in another language” (ahem) static methods and even static classes of methods are fairly common for a large number of common functionalities. Maybe think “hand calculator” … the ones with all those cool engineering functions built in. But that does call to mind a question: when is it better to pack such things into a class that you have to instantiate first to get all the cool class methods, and when is it better to have a passle of statics? What are the underlying efficiencies and costs? Once upon a time, I think “static” had specialized memory implications … Not certain in Python much less any other language now.

Avatar image for Roy Telles

Roy Telles on Aug. 17, 2020

Just wanna say it was a good point to make (and this actually may be the crux of static methods) in saying that the static method simplifies testing in that we don’t have to worry about instantiating our object first, and then passing in arguments to its functions.

Avatar image for Patrick

Patrick on Jan. 15, 2022

Do PyCharm or Python use measurements in feet and inches? If you could make a video on this. Or maybe I could, once I know how measurements work, may I?

Become a Member to join the conversation.