Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions 13_object_oriented_programming_advanced.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
" - [Composition](#Composition)\n",
" - [`super()`](#super())\n",
" - [Quiz on Inheritance](#Quiz-on-Inheritance)\n",
" - [Exercise: Child Eye Color](#Exercise:-Child-Eye-Color)\n",
" - [Exercise: Triathlete](#Exercise:-Triathlete)\n",
" - [Abstract Classes](#Abstract-Classes)\n",
" - [Quiz on Abstraction](#Quiz-on-Abstraction)\n",
" - [Exercise: Banking System](#Exercise:-Banking-System)\n",
Expand Down Expand Up @@ -494,22 +494,21 @@
"id": "36",
"metadata": {},
"source": [
"### Exercise: Child Eye Color\n",
"### Exercise: Triathlete\n",
"\n",
"In this exercise, we will implement the following simplified theory on how to predict a child's eye color, based on the eye color of its parents.\n",
"A triathlon is a race consisting of three disciplines: **swimming**, **cycling**, and **running**, completed back-to-back.\n",
"\n",
"We assume that the only existing eye colors are <span style=\"color:blue\">blue</span> and <span style=\"color:brown\">brown</span>. We also assume the following rules:\n",
"- If both parents have <span style=\"color:brown\">brown</span> eyes, their child will also have <span style=\"color:brown\">brown</span> eyes.\n",
"- If both parents have <span style=\"color:blue\">blue</span> eyes, their child will also have <span style=\"color:blue\">blue</span> eyes.\n",
"- If one parent has <span style=\"color:brown\">brown</span> eyes and the other one has <span style=\"color:blue\">blue</span> eyes, the dominant color will be <span style=\"color:brown\">brown</span>.\n",
"We model this using the following class hierarchy:\n",
"- **Swimmer** with attribute `swim_time`.\n",
"- **Cyclist** with attribute `bike_time`.\n",
"- **Runner** with attribute `run_time`.\n",
"- **Triathlete** with attributes `name` and `total_time`, which is the sum of all three split times inherited from `Swimmer`, `Cyclist`, and `Runner`.\n",
"\n",
"<div class=\"alert alert-block alert-warning\">\n",
" <h4><b>Question</b></h4>\n",
" <ul>\n",
" <li>Complete the solution function such that it defines classes <strong>Mother</strong> and <strong>Father</strong>, each with an attribute for the eye color.</li>\n",
" <li>Define class <strong>Child</strong>, which inherits from <strong>Mother</strong> and <strong>Father</strong> and has an attribute called <strong>eye_color</strong>.\n",
" Then, based on the eye colors of the parents, calculate the child's eye color, according to the rules above and assign it to the attribute <code>eye_color</code>.</li>\n",
" <li>Create an instance of <strong>Child</strong>, which is being initialized by using the arguments passed in the solution function, namely the eye colors of its parents. Lastly, return this instance.</li>\n",
" <li>Define the four classes described above.</li>\n",
" <li>Create and return an instance of <code>Triathlete</code> using the arguments passed to the solution function.</li>\n",
" </ul>\n",
"</div>"
]
Expand All @@ -533,19 +532,21 @@
"source": [
"%%ipytest\n",
"\n",
"def solution_child_eye_color(mother_eye_color: str, father_eye_color: str) -> list:\n",
"def solution_triathlete(name: str, swim_time: float, bike_time: float, run_time: float):\n",
" \"\"\"\n",
" Given the eye colors of the mother and father, defines the eye color of the child.\n",
" The possible eye colors are: brown or blue, with brown being the dominant one.\n",
" This function defines a class Mother and a class Father, which are used to create an instance of the class Child.\n",
" It returns an instance of the class Child with the eye color defined by the parents.\n",
" Defines three parent classes: Swimmer (swim_time), Cyclist (bike_time), Runner (run_time).\n",
" Triathlete inherits from all three.\n",
" Triathlete has attributes name and total_time, which is the sum of all three split times.\n",
"\n",
" Args:\n",
" mother_eye_color (str): Eye color of the mother.\n",
" father_eye_color (str): Eye color of the father.\n",
" name (str): Name of the triathlete.\n",
" swim_time (float): Swim split time in hours.\n",
" bike_time (float): Bike split time in hours.\n",
" run_time (float): Run split time in hours.\n",
" Returns:\n",
" - an instance of class Child\n",
" - an instance of class Triathlete\n",
" \"\"\"\n",
"\n",
" return"
]
},
Expand Down
84 changes: 42 additions & 42 deletions tutorial/quiz/object_oriented_programming_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ def __init__(self, title=""):
q1 = Question(
question="Which special method is used for object initialization in Python?",
options={
"__init__": "Correct! The `__init__` method is called when an object is created and is used to initialize the object.",
"__repr__": "The `__repr__` method is used to provide an unambiguous string representation of an object.",
"__eq__": "The `__eq__` method is used to define equality comparison between objects.",
"__init__": "Correct! The <code>__init__</code> method is called when an object is created and is used to initialize the object.",
"__repr__": "The <code>__repr__</code> method is used to provide an unambiguous string representation of an object.",
"__eq__": "The <code>__eq__</code> method is used to define equality comparison between objects.",
},
correct_answer="__init__",
hint="This method is automatically called when an object is instantiated.",
Expand All @@ -27,11 +27,11 @@ def __init__(self, title=""):
)

q3 = Question(
question="What is the purpose of the `super()` function in Python?",
question="What is the purpose of the <code>super()</code> function in Python?",
options={
"To call a method from the parent class": "Correct! `super()` is used to call a method from the parent class.",
"To create a derived class": "Incorrect. `super()` is not used for creating derived classes.",
"To initialize an object": "Incorrect. Object initialization is done using the `__init__` method.",
"To call a method from the parent class": "Correct! <code>super()</code> is used to call a method from the parent class.",
"To create a derived class": "Incorrect. <code>super()</code> is not used for creating derived classes.",
"To initialize an object": "Incorrect. Object initialization is done using the <code>__init__</code> method.",
},
correct_answer="To call a method from the parent class",
hint="This function is used to access inherited methods.",
Expand All @@ -58,9 +58,9 @@ def __init__(self, title=""):
q1 = Question(
question="Which module in Python is used to create abstract classes?",
options={
"abc": "Correct! The `abc` module provides the infrastructure for defining abstract base classes.",
"abstract": "There is no module named `abstract` in Python.",
"abstractmodule": "There is no module named `abstractmodule` in Python.",
"abc": "Correct! The <code>abc</code> module provides the infrastructure for defining abstract base classes.",
"abstract": "There is no module named <code>abstract</code> in Python.",
"abstractmodule": "There is no module named <code>abstractmodule</code> in Python.",
},
correct_answer="abc",
hint="This module's name is an abbreviation for 'Abstract Base Classes'.",
Expand Down Expand Up @@ -100,22 +100,22 @@ def __init__(self, title=""):
question="Which decorator is used to define a method that belongs to the class rather than an instance?",
options={
"@staticmethod": "Incorrect. A static method does not belong to the class or instance.",
"@classmethod": "Correct! A class method belongs to the class and takes `cls` as its first parameter.",
"@property": "Incorrect. The `@property` decorator is used to define getter methods.",
"@abstractmethod": "Incorrect. The `@abstractmethod` decorator is used in abstract classes.",
"@classmethod": "Correct! A class method belongs to the class and takes <code>cls</code> as its first parameter.",
"@property": "Incorrect. The <code>@property</code> decorator is used to define getter methods.",
"@abstractmethod": "Incorrect. The <code>@abstractmethod</code> decorator is used in abstract classes.",
},
correct_answer="@classmethod",
hint="This method takes `cls` as its first parameter.",
hint="This method takes <code>cls</code> as its first parameter.",
shuffle=True,
)

q2 = Question(
question="What is the purpose of the `@property` decorator?",
question="What is the purpose of the <code>@property</code> decorator?",
options={
"To define a computed attribute": "Correct! The `@property` decorator is used to define computed attributes.",
"To define a static method": "Incorrect. Static methods are defined using the `@staticmethod` decorator.",
"To define a class method": "Incorrect. Class methods are defined using the `@classmethod` decorator.",
"To define an abstract method": "Incorrect. Abstract methods are defined using the `@abstractmethod` decorator.",
"To define a computed attribute": "Correct! The <code>@property</code> decorator is used to define computed attributes.",
"To define a static method": "Incorrect. Static methods are defined using the <code>@staticmethod</code> decorator.",
"To define a class method": "Incorrect. Class methods are defined using the <code>@classmethod</code> decorator.",
"To define an abstract method": "Incorrect. Abstract methods are defined using the <code>@abstractmethod</code> decorator.",
},
correct_answer="To define a computed attribute",
hint="This decorator allows you to define methods that can be accessed like attributes.",
Expand All @@ -126,20 +126,20 @@ def __init__(self, title=""):
question="Which decorator is used to define a method that does not access the class or instance?",
options={
"@staticmethod": "Correct! A static method does not access the class or instance.",
"@classmethod": "Incorrect. A class method accesses the class using `cls`.",
"@property": "Incorrect. The `@property` decorator is used to define getter methods.",
"@abstractmethod": "Incorrect. The `@abstractmethod` decorator is used in abstract classes.",
"@classmethod": "Incorrect. A class method accesses the class using <code>cls</code>.",
"@property": "Incorrect. The <code>@property</code> decorator is used to define getter methods.",
"@abstractmethod": "Incorrect. The <code>@abstractmethod</code> decorator is used in abstract classes.",
},
correct_answer="@staticmethod",
hint="This method is often used for utility functions.",
shuffle=True,
)

q4 = Question(
question="A method with which decorator takes `cls` as its first parameter?",
question="A method with which decorator takes <code>cls</code> as its first parameter?",
options={
"@classmethod": "Correct! A class method is bound to a class rather than its instances and the parameter `cls` represents the class itself.",
"@staticmethod": "A static method does not have access to `cls` or `self` and cannot modify the class state.",
"@classmethod": "Correct! A class method is bound to a class rather than its instances and the parameter <code>cls</code> represents the class itself.",
"@staticmethod": "A static method does not have access to <code>cls</code> or <code>self</code> and cannot modify the class state.",
"@abstractmethod": "This decorator defines a method in an abstract class that **must** be implemented by all its concrete subclasses.",
},
correct_answer="@classmethod",
Expand All @@ -148,27 +148,27 @@ def __init__(self, title=""):
)

q5 = Question(
question="What is the purpose of the `@classmethod` decorator?",
question="What is the purpose of the <code>@classmethod</code> decorator?",
options={
"To define a method that belongs to the class rather than an instance": "Correct! A class method belongs to the class and takes `cls` as its first parameter.",
"To define a method that belongs to the class rather than an instance": "Correct! A class method belongs to the class and takes <code>cls</code> as its first parameter.",
"To define a method that does not access the class or instance": "Incorrect. This describes a static method.",
"To define a computed attribute": "Incorrect. Computed attributes are defined using the `@property` decorator.",
"To define an abstract method": "Incorrect. Abstract methods are defined using the `@abstractmethod` decorator.",
"To define a computed attribute": "Incorrect. Computed attributes are defined using the <code>@property</code> decorator.",
"To define an abstract method": "Incorrect. Abstract methods are defined using the <code>@abstractmethod</code> decorator.",
},
correct_answer="To define a method that belongs to the class rather than an instance",
hint="This method takes `cls` as its first parameter.",
hint="This method takes <code>cls</code> as its first parameter.",
shuffle=True,
)

q6 = Question(
question="What is the difference between `@staticmethod` and `@classmethod`?",
question="What is the difference between <code>@staticmethod</code> and <code>@classmethod</code>?",
options={
"`@staticmethod` does not access the class or instance, while `@classmethod` takes `cls` as its first parameter": "Correct! This is the key difference between the two decorators.",
"`@staticmethod` is used for utility functions, while `@classmethod` is used for abstract methods": "Incorrect. Abstract methods are unrelated to these decorators.",
"`@staticmethod` is faster than `@classmethod`": "Incorrect. Performance is not the defining difference.",
"`@staticmethod` is used for computed attributes, while `@classmethod` is used for class-level attributes": "Incorrect. Computed attributes are defined using `@property`.",
"<code>@staticmethod</code> does not access the class or instance, while <code>@classmethod</code> takes <code>cls</code> as its first parameter": "Correct! This is the key difference between the two decorators.",
"<code>@staticmethod</code> is used for utility functions, while <code>@classmethod</code> is used for abstract methods": "Incorrect. Abstract methods are unrelated to these decorators.",
"<code>@staticmethod</code> is faster than <code>@classmethod</code>": "Incorrect. Performance is not the defining difference.",
"<code>@staticmethod</code> is used for computed attributes, while <code>@classmethod</code> is used for class-level attributes": "Incorrect. Computed attributes are defined using <code>@property</code>.",
},
correct_answer="`@staticmethod` does not access the class or instance, while `@classmethod` takes `cls` as its first parameter",
correct_answer="<code>@staticmethod</code> does not access the class or instance, while <code>@classmethod</code> takes <code>cls</code> as its first parameter",
hint="Think about the parameters each decorator uses.",
shuffle=True,
)
Expand Down Expand Up @@ -207,9 +207,9 @@ def __init__(self, title=""):
question="What is the purpose of encapsulation in OOP?",
options={
"To bundle data and methods into a single unit": "Correct! Encapsulation bundles data and methods into a single unit.",
"To define abstract methods": "Incorrect. Abstract methods are defined using the `abc` module.",
"To define abstract methods": "Incorrect. Abstract methods are defined using the <code>abc</code> module.",
"To create a class that cannot be inherited": "Incorrect. Encapsulation does not restrict inheritance.",
"To define static methods": "Incorrect. Static methods are defined using the `@staticmethod` decorator.",
"To define static methods": "Incorrect. Static methods are defined using the <code>@staticmethod</code> decorator.",
},
correct_answer="To bundle data and methods into a single unit",
hint="Encapsulation is one of the fundamental principles of OOP.",
Expand All @@ -233,11 +233,11 @@ def __init__(self, title=""):
class OopAdvancedAttrsDataclasses(Quiz):
def __init__(self, title=""):
q1 = Question(
question="What is something that `attrs` provides but `dataclasses` doesn't?",
question="What is something that <code>attrs</code> provides but <code>dataclasses</code> doesn't?",
options={
"__init__()": "Both packages automatically generate `__init__()`: `dataclasses` uses the `@dataclass` decorator, while `attrs` uses `@define`.",
"__repr__()": "Both packages automatically generate `__repr__()` to help you easily print a class instance.",
"validators": "Correct! You need to define the attribute as a `field()` and then use the validator decorator.",
"__init__()": "Both packages automatically generate <code>__init__()</code>: <code>dataclasses</code> uses the <code>@dataclass</code> decorator, while <code>attrs</code> uses <code>@define</code>.",
"__repr__()": "Both packages automatically generate <code>__repr__()</code> to help you easily print a class instance.",
"validators": "Correct! You need to define the attribute as a <code>field()</code> and then use the validator decorator.",
},
correct_answer="validators",
hint="",
Expand Down
Loading