Stephen Gruppetta Profile picture
Apr 3 20 tweets 6 min read Twitter logo Read on Twitter
Object-Oriented Python at the Hogwarts School of Codecraft and Algorithmancy
---
Year 4:
More interaction between classes
---

Year 3 was a busy year. Here's were we left in Year 3

/1 See year 3 thread for code in ALT text
In earlier Years, we discussed how we should think of the problem from the point of view of the "objects" that make sense to a human describing the problem

In our example so far, we have:
• Wizard
• House
• Wand

An object that belongs to these classes has _attributes_

/2
You've already come across the two types of attributes an object can have

• Data attributes are variables that are connected to the instance of the class. They are also called instance variables

• Methods are functions connected to the instance of the class

/3
Let's add more classes to describe our situation better

One of the last additions in Year 3 was the `Wand` class. It has a method called `cast_spell()`

Perhaps, we could also create a `Spell` class

/4 import random  # ...  class Spell:     def __init__(self, na
We'll keep this class simple and give it three data attributes and one method

The method `is_successful()` returns a Boolean to indicate whether the spell worked!

/5
Now, we can finish writing the `cast_spell()` method in the `Wand` class

Since we have a `Spell` class, we can pass an object of type `Spell` to this method

/6 # ...   class Wand:     def __init__(self, wood, core, lengt
However, the `Wizard` class can also have a `cast_spell()` method. It's the wizard with the wand that cast spells, right?

Since `Wand` and `Wizard` are different classes, they could have methods with the same names—these don't conflict with each other

/7 import random  class Wizard:     # ...      def cast_spell(s
Whether you want to have two classes with methods with the same name depends on what you're trying to achieve

As this is a demonstration example, I'll use the same name to highlight how `.cast_spell()` in `Wand` and `.cast_spell()` in `Wizard` are different methods

/8
Let's make sure these changes work

Note how Hermione has no wand, so can't cast spells

And each time the same spell is cast, the likelihood of success is random and depends on the spell's difficulty

/9 from hogwarts_magic import Wizard, House, Wand, Spell  harry
But wait a second! The wizard's skill surely must be a factor on how likely he or she is to cast the spell successfully.

Dumbledore is going to have a higher success rate than Crabbe!

Let's make some changes. First, let's add a new data attribute and method to `Wizard`

/10 import random  class Wizard:     def __init__(self, name, pa
Next we need to pass this information to the `Wand` class when the wizard casts a spell

You pass `self` to `self.wand.cast_spell(spell, self)`

This means `.cast_spell()` in the `Wand` class knows who the wizard casting the spell is (`self` in `Wizard` refers to the wizard)

/11 import random  class Wizard:     # ...     def cast_spell(se
This means that we need to update `.cast_spell()` in `Wand`, too

And while we're in the `Wand` class, let's account for wands having different powers

We've added another parameter to `Wand.cast_spell()`

/12 # ... class Wand:     def __init__(self, wood, core, length,
Note that `spell.​is_successful()` now needs information about the wand and the wizard

As you're in the `Wand` class, `self` refers to the wand

And yes, we need to update the `Spell` class, too

/13 # ...  class Spell:     # ...      def is_successful(self, w
You'll need to find the right values for the spell difficulties, wand powers, and wizard skills that make sense!

But I'll leave that as an exercise for you to do!

/14
And here are a few more additions you can make:

• Create a `.spells_known` attribute in `Wizard`. This should be a list. Then you can add a `.learn_spell()` method which adds spells to this list
• When a wizard casts a spell, he or she needs to know that spell first!

/15
I'll let your imagination (plus: see homework below) suggest more additions to these classes and how we can link them together

Here's the classes we have so far, before you make your modifications

/16
An important note: this example is a demonstration example. I wanted to show an example that goes beyond a couple of attributes, but without going through hundreds of lines of code in a Twitter thread

There, I've said it!

/17
The key point to take from Year 4 is that when using classes and OOP, we want to "encapsulate" the data and functionality for an object into one unit—the class

/18
Once the class and its data attributes and methods are written, a user of the class can deal with these objects at a "higher level"

`harry.cast_spell()` means you want Harry to cast a spell. You're not concerned too much about what's happening "behind the scenes"

/19
Your homework over the holidays: Expand the classes above further

Optional homework: If you have access to GPT-4, paste the code we've written so far and ask it to suggest other methods you could write and new classes that would fit in this project

---
Year 5: Inheritance

/20

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Stephen Gruppetta

Stephen Gruppetta Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @s_gruppetta_ct

Apr 1
Slightly off-topic from my usual on this account—but a lot of my work is also linked to children's education (coding primarily, but let's think beyond subjects)

I've taken a stab at what "homework" in the near-future could look like, using a GPT-first, cheat-proof approach…

/1 1. Write an outline of your...
It solves reasonably well the problem of "cheating" by incorporating GPT into the process and requiring the whole conversation to be submitted, including first drafts, suggestions by GPT, second drafts, and so on

Teachers can craft the right prompts that all students use

/2
But main point is not that it's cheat-proof but that it leverages the opportunities LLMs provide to improve learning

I collated some ideas & examples of how learning (children, but also adult-learning) could change soon

Consider as work-in-progress

codetoday.co.uk/post/learning-…

/3
Read 4 tweets
Mar 5
What Python data type would [a multi-storey car park] be?
–––
You drive into a multi-storey car park, find a spot to park, and then you ask yourself: "what data structure would best represent this car park", of course

Let's explore

1/ Model of a multi-storey car...
Let's name the object `car_park` and it contains several levels. I'll also look at `level` which represents one the levels. This will be a different data type

The car park has a fixed number of levels which don't change. Therefore, `car_park` is immutable

2/
You can count the levels – `len(car_park)` exists
You can determine whether `level` is in `car_park`, so `car_park` is a container
You can go through the levels one after the other, so `car_park` is iterable

These three properties make `car_park` a collection, too

3/
Read 15 tweets
Mar 4
These thought experiments help us focus on real decisions we need to make when choosing what data types to use in programs

It's not just about the data itself but how you're likely to use it

For example, in this restaurant tables scenario, I opted for dictionaries, but…

/1
It depends whether we want to prioritise the use case when the tables are being used during normal service, with diners sitting on them and waiters taking their orders and bringing them food [dictionary is a good choice]…

/2
…or if you want to prioritise the setting up process before the restaurant opens its doors when staff go from one table to the next to clean it and set it up. For this, you could be tempted to use a sequence instead, such as a tuple or list

/3
Read 7 tweets
Feb 26
Let's write this game in 20 tweets…
Yes, just 20

Ready?

Go…

• Balls appear in random positions every few seconds and are tossed upwards with random velocities
• Click close to the ball to "bat it up"
• How long until you lose 10 balls?

/1
You'll work in 2 scripts–the 1st is `juggling_balls.py` where you'll define the class `Ball` which inherits from `turtle.Turtle`

The bounds of where the ball is created are passed as arguments to the function's `__init__()` method

Ball's colour, shape, and position are set

/2 # juggling_balls.py  import random import turtle  class Ball
In the second script named `juggling_balls_game.py` you can create the screen, set its size, and create two instances of `Ball` to test the class's `__init__()` method so far

/3 # juggling_balls_game.py  import turtle  from juggling_balls
Read 23 tweets
Feb 24
What happens when you reverse a `range` object in Python?

A range object is a sequence. This means it is:
• An iterable
• A container
• A sized object (it has a length)
• Indexed using an integer

It also means it can be reversed as all sequences are reversible

/1 # A `range` object is a seq...
You can refresh your memory about the ins and outs of the key data structure categories in this series:

/2
When you reverse a range using the shorthand `[::-1]`, you'll get another range object with the required `start`, `stop`, and `step` arguments:

>>> some_range = range(10)

>>> some_range[::-1]
range(9, -1, -1)

/3 >>> some_range = range(10) ...
Read 6 tweets
Feb 19
––– Mid-Series Roundup (Day 5.5) –––

Let's review the terms we've seen so far but in a different order to how I presented them in this series

Let's start with three “top-level” categories:

• Iterable
• Container
• Sized

1/
Each category provides one characteristic:

• Iterable: can be iterated

These classes normally have `__iter__()` defined, but could also only have `__getitem__()`

2/
• Container: membership of a container is clearly defined

This is done through the `__contains__()` method of the class.

3/
Read 17 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!

:(