From 0459123abf06b13f5c58e38ce7371760996e5183 Mon Sep 17 00:00:00 2001 From: Poonam Rajput Date: Mon, 27 Jul 2026 11:52:43 +0100 Subject: [PATCH 1/3] edit sprint 5 tools prep for methods prioritising encapsulation and expanding example --- .../en/module/decomposition/methods/index.md | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/common-content/en/module/decomposition/methods/index.md b/common-content/en/module/decomposition/methods/index.md index dff21489e..a8be2803b 100644 --- a/common-content/en/module/decomposition/methods/index.md +++ b/common-content/en/module/decomposition/methods/index.md @@ -5,7 +5,8 @@ objectives = [ "Define a method.", "Define a free function.", "Explain why methods can be more useful than free functions.", - "Implement a method on a class.", + "Explain how encapsulation can .", + "Amend a method on a class.", ] [build] @@ -38,7 +39,7 @@ class Person: return self.age >= 18 imran = Person("Imran", 22, "Ubuntu") -print(imran.is_adult()) +print(imran.is_adult()) # True ``` This has a few advantages over {{}}A free function is a function that isn't a method. It isn't bound to a particular type (but may take parameters).{{}}. @@ -50,13 +51,36 @@ Think of the advantages of using methods instead of free functions. Write them d Expand for some answers after you've listed your own. -* Ease of documentation - it makes it easier to find all of the things related to a string (or a Person) if they're attached to that type. -* Encapsulation - if we change the implementation of `Person` (e.g. we start storing a date of birth instead of an age), it's more obvious what things we need to change. +- Encapsulation - if we change the implementation of `Person` (e.g. we start storing a date of birth instead of an age), it's more obvious what things we need to change. +- Ease of documentation - it makes it easier to find all of the things related to a string (or a Person) if they're attached to that type. {{}} +Consider this free function called `drivers_license_check` which uses the Person class method `is_adult` outside of the class: + +```python +def drivers_license_check(person: Person): + if person.is_adult() == True: + return 'Valid drivers license' + + return 'This person is underage!' + +print(drivers_license_check(imran)) # returns 'Valid drivers license' +``` + {{}} -Change the `Person` class to take a date of birth (using [the standard library's `datetime.date` class](https://docs.python.org/3/library/datetime.html#datetime.date)) and store it in a field instead of `age`. -Update the `is_adult` method to act the same as before. +1. Add the `drivers_license_check` free function and the `is_adult` method into your code just like above, make sure your code currently gives the expected final print. +1. Change the `Person` class to take a date of birth (using [the standard library's `datetime.date` class](https://docs.python.org/3/library/datetime.html#datetime.date)) and store the `date of birth` in a field instead of `age` (it should be a `str`). Don't change anything else. +1. **Try to run your code**, how does this change break your code. What kind of error do you get? Is it helpful in identifying where your next change needs to be? +1. Update the `is_adult` method so the error is fixed. Using the `drivers_license_check` function check everything runs as expected, it should return "Valid drivers license". _You should not change `drivers_license_check`_. + {{}} + +{{}} +Take a moment to consider what we've done here. How has **encapsulation** helped us make changes to our class? + +We've changed a property of Person, seen errors inform us about how that change affected a method on the class, and then amended that method so we were maintaining the behaviour of the class. The behaviour of `drivers_license_check` did not need to change - we can change the internal implementation of the class without affecting external code. + +_Encapsulation is a widely known principle in object-oriented programming, consider reading around in online to find out more_ + {{}} From 37ac0068ca9419420cc5a782139b14ea6a0cdf81 Mon Sep 17 00:00:00 2001 From: Poonam Rajput Date: Mon, 27 Jul 2026 11:55:48 +0100 Subject: [PATCH 2/3] finish learning objective --- common-content/en/module/decomposition/methods/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common-content/en/module/decomposition/methods/index.md b/common-content/en/module/decomposition/methods/index.md index a8be2803b..a9c9e32e5 100644 --- a/common-content/en/module/decomposition/methods/index.md +++ b/common-content/en/module/decomposition/methods/index.md @@ -5,7 +5,7 @@ objectives = [ "Define a method.", "Define a free function.", "Explain why methods can be more useful than free functions.", - "Explain how encapsulation can .", + "Explain how encapsulation can benefit class design.", "Amend a method on a class.", ] From 9dd32c51f1c8fff8f27123c86dc75abb173b419c Mon Sep 17 00:00:00 2001 From: Poonam Rajput Date: Mon, 27 Jul 2026 12:24:02 +0100 Subject: [PATCH 3/3] extend sprint 5 dataclasses introduce another example (Animal class) to make exercise more novel, extend exercise to add new method --- .../module/decomposition/dataclasses/index.md | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/common-content/en/module/decomposition/dataclasses/index.md b/common-content/en/module/decomposition/dataclasses/index.md index 2df62c974..02d83e598 100644 --- a/common-content/en/module/decomposition/dataclasses/index.md +++ b/common-content/en/module/decomposition/dataclasses/index.md @@ -27,7 +27,7 @@ Equality is one: ideally two value objects are the same if their fields are the class Person: def __init__(self, name: str, age: int, preferred_operating_system: str): self.name = name - self.age = age + self.age = age self.preferred_operating_system = preferred_operating_system imran = Person("Imran", 22, "Ubuntu") @@ -54,16 +54,17 @@ Python has a useful {{}}A decorator from dataclasses import dataclass @dataclass(frozen=True) -class Person: +class Animal: name: str + species: str age: int - preferred_operating_system: str + noise: str -imran = Person("Imran", 22, "Ubuntu") # We can call this constructor - @dataclass generated it for us. -print(imran) # Prints Person(name='Imran', age=22, preferred_operating_system='Ubuntu') +indigo = Animal("indigo", "cat", 2, "meow") # We can call this constructor - @dataclass generated it for us. +print(indigo) # Prints Animal(name='Indigo', species='cat', age=2, noise='meow') -imran2 = Person("Imran", 22, "Ubuntu") -print(imran == imran2) # Prints True +indigo2 = Animal("indigo", "cat", 2, "meow") +print(indigo == indigo2) # Prints True ``` The `dataclass` decorator generated a constructor, a `__str__` method (which is called when string formatting the value), and a custom `__eq__` method (which is called when comparing two values). This saves us having to write all of that code. @@ -71,7 +72,9 @@ The `dataclass` decorator generated a constructor, a `__str__` method (which is Other languages have a similar idea of a value type, and tools to help make them, such as [Java's record classes](https://docs.oracle.com/en/java/javase/17/language/records.html) and [C#'s' structure types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/struct). {{}} -Write a `Person` class using `@datatype` which uses a `datetime.date` for date of birth, rather than an `int` for age. +Convert your existing `Person` class into a value type using `@datatype` so you can print the class (and see it's type and fields) and compare class instances that are identical. Make sure your `is_adult` method and `drivers_license_check` free function both work as normal. + +Make a new method on your Person class - `greet` which should return `"Hello !"` when used. -Re-add the `is_adult` method to it. +Take a look at the [`@datatype` documentation](https://docs.python.org/3/library/dataclasses.html) - what does `frozen=True` do to the class? What other options could you play around with and explore? {{}}