Typefully

Object-Oriented Programming Series: 3. Defining Methods

Avatar

Share

 • 

3 years ago

 • 

View on X

Object-Oriented Python at the Hogwarts School of Codecraft and Algorithmancy --- Year 3: Defining Methods --- Students are no longer fresh-faced first years, but there's still a lot to learn. Real stuff starts this Year as they learn to define methods to add functionality
Here are Years 1 and 2 in case you need to revise: twitter.com/s_gruppetta_ct/status/1641474113624760321 twitter.com/s_gruppetta_ct/status/1641121936414736385 We'll carry on from the `Wizard` class from Year 2, but we'll add more classes this Year, too
We ended last Year with a `Wizard` class with some data attributes Three of them are assigned when you create the class: `.name` `.patronus` `.birth_year` The other two are empty for now* * They're not really empty—they contain the object `None`
However, this class only has data attributes so far What makes an object more useful is when it also has built-in functionality, not just stored data We use functions to get things done in a program and we can add functions within a class, too — we call these _methods_
Let's create a method to assign a wand to a wizard Note that as we're now in Year 3, we'll separate our code into separate files. This one is called `hogwarts_magic.​py` and only contains the `Wizard` class for now. It will contain other classes later
You define a method in the same way you define functions — recall that a method is a function! However, note that the definition is within the class The method `assign_wand()` has two parameters: • `self` • `wand` In Year 2 you learnt about `self`
`self` is a placeholder you use to refer to the object you'll create later using this class Many methods have `self` as the first parameter — in fact, if you're using an IDE or similar tools, the parameter `self` may have been autocompleted for you!
We call these _instance methods_ They are methods which each instance you create of this class will have
The method does two things: • It assigns the argument `wand` to the data attribute of the object `self.wand`. This way, the object carries this information with it! • It prints out a message to tell the user what wand was assigned
Let's try out this method in a new file called `making_magic.​py` You import the class from the file (we normally call this 'module') in which you define the class and create two instances, as you did at the end of Year 2 Initially, the wizards have no wands
The output of `print(harry.​wand)` is `None` However, the wizards get a wand when you call the `.assign_wand()` method `harry.​assign_wand()` only affects the object named `harry`. This is the beauty of OOP. Once you create self-contained classes, they're simpler to use
Note how there's only one argument passed when you call `.assign_wand()` even though there are two parameters in the method's definition The first parameter `self` is dealt with automatically as it represents the object itself
`harry.​assign_wand("description")` is equivalent to `Wizard.​assign_wand(harry, "description")` Exercise: Create another method called `assign_house()` and test it
However, I'll take a different route to assign a house to a wizard, and I'll also come back to the wand issue! In Year 1, we briefly discussed how OOP encourages you to look at the problem from a more "human" perspective twitter.com/s_gruppetta_ct/status/1641121965263171586
What do I mean? Ask yourself: • What are the 'things' that matter for a human looking at this problem? • What 'things' or 'objects' are needed to understand the problem?"
The words 'things' and 'objects' are used loosely here, not only because a wizard, for example, is neither, but because sometimes you may need something more abstract We've already seen `Wizard` But wands and houses are also 'things' or 'objects' of relevance
So let's create classes for each one, starting from `House` Its data attributes could include: • `.name` • `.founder` • `.colours` • `.animal` • `.members` • `.points`
Note how the first four data attributes are directly linked to arguments you pass when you create the instance of `House` `self.members` and `self.points` are initialised to an empty list and to 0 respectively You'll update these data attributes soon
Let's add some methods, too Three of these methods update a data attribute. They're changing the state of the object The final method doesn't make any changes to the object. Instead, it returns some information. In this case it returns a dictionary with relevant values
Now you have the `House` class, look back at `Wizard` See what we did with `assign_wand()`? We added a string with the description on the wand. Therefore, the `.wand` attribute contains a string
You could do the same thing with the house and store a string with the house name in `.house` But now we have a `House` class, and therefore objects of type `House`, we can store an instance of `House` in `self.​house` instead of a plain string with the house name
There are two things happening in `assign_house()` in the `Wizard` class: 1. The value passed to the method is assigned to the data attribute `self.​house`. This value will be an instance of type `House`. You could use type hinting and input validation, too
2. The `House` instance itself is modified: `house` is an instance of `House` `house.add_member()` calls the `.add_member()` method for this `House` instance You pass `self` to this method — that's the wizard, since you're in the `Wizard` class
Recall that `self` is a placeholder to refer to the instance of a class Note that when you use `self` within the `Wizard` class, it refers to the `Wizard` instance… …and when you use `self` in the `House` class definition, it refers to the `House` instance
Let's test these new additions in `making_magic.​py` You create the two `Wizard` instances and a `House` instance Initially, the wizard has no house and the house has no members But after calling `harry.assign_house(gryffindor)`, both associations are in place
Let's start wrapping up this Year. The summer break is fast approaching No one said your journey through Hogwarts School of Codecraft and Algorithmancy would be easy! What happens if you also add: `gryffindor.add_member(harry)` in `making_magic.​py` Try it out… I'll wait
"Harry Potter" now appears twice in the list of Gryffindor members He was added when you called `harry.assign_house(gryffindor)` and again in `gryffindor.add_member(harry)` You can avoid this with a small change in `.add_member()` in the `House` class
Final update for Year 3. You can update the code so that `Wand` is also a class Here's an idea of what this could look like and what methods we could add You'll learn spells in Year 4!
Here's how we can check this works - see this version of `making_magic.​py` - When writing classes, you put all the hard work in creating the classes and making sure the links and associations and behaviours are all right… …but then, using the classes is safer and easier
--- Terminology Corner --- • Instance method is a function that's part of a class (method) which is attached to each instance of the class An instance method always takes the object as its first argument. This is implicit when you call the method—you don't need to add it
You've earned your "summer break" - it's a longer one as Year 4 starts after the weekend… …but there may be some "revision" tweets over the weekend on Year 1, 2, and 3 material --- Year 4: More interaction between classes
Avatar

Stephen Gruppetta

@s_gruppetta_ct

Constantly looking for innovative ways to talk and write about Python • Mentoring learners • Writing about Python • Writing about technical writing