In this lesson, you'll return to your empty Ingredient class and start to experiment with it.
Define an Empty Class
Check out the code below:
class Ingredient:
"""Creates an empty Ingredient object."""
pass
i = Ingredient()
i.name = "carrot"
print(i.name) # OUTPUT: carrot
In this code snippet, you've defined an empty class. Then, you created an instance of that empty class. The instance followed the blueprint of your empty class, which means it'll be empty as well.
Right after that, you assigned a value to a variable inside the instance:
i.name = "carrot"
And now this instance variable points to a value that you can print out.
Tasks
- Recreate this code snippet in a local script.
- Try printing
nameinstead ofi.name. What do you get as a result? Why?
You've created a variable inside of the namespace of your Ingredient object, i. This means that the value will only be accessible through i.name and not just name.
You could have a variable name in the global scope of your script, and it won't interfere with i.name.
The Constructor Method
While it's possible to assign instance variables in the way you just did, this is rare in practice. Instead, you want to use your class as a blueprint that defines what variables each instance should have.
The blueprint for your class constructor is Python's dunder init (__init__()) method. This method gets called when you're creating a new instance. Any attributes you define here will apply to all instances of the class you'll create:
class Ingredient:
"""Models an Ingredient. Currently only carrots!"""
def __init__(self):
self.name = "carrot"
i = Ingredient()
print(i.name) # OUTPUT: carrot
In this code snippet, you wrote an __init__() method for your Ingredient class. You might recognize most of the syntax of this method, and if you do, it'll likely remind you of a function definition. Indeed, you can think of methods as functions that belong to an object. There are a few specialties about them that you'll get to know about in a bit.
Note: Don't worry about self too much at this point. Explore what writing this method does, and you'll dig deeper in one of the upcoming lessons.
By implementing the dunder init method of your Ingredient class, you've hard-coded a .name attribute for each Ingredient object that you'll create. All of them will follow the same blueprint that you've defined.
This means that you hard-coded the .name as "carrot". You won't need to reach into the instance namespace from outside to assign a .name, each object will already have it assigned:
c = Ingredient()
print(c.name) # OUTPUT: carrot
Play around with the code and create some more instances of your Ingredient class. Double-check whether they all have a .name attribute and what its value is.
But you don't only want to cook with carrots! That's a little much, even for some carrot soup. In the next lesson, you'll learn how you can adapt your dunder init method so it accepts arguments and how that allows you to create Ingredient objects that each have different .name attributes.
Additional Resources
- Official Python Tutorial: Class Objects
- Think Python: Chapter 15 Classes and objects
Summary: Python Classes, Objects and Instance Variables
- The
__init__()method is called when instantiating a new object - You can create custom dunder init methods
- Custom init methods can contain custom instance variables