Skip to content

Commit

Permalink
Object-oriented: Add simpler examples, update quiz and exercises (#249
Browse files Browse the repository at this point in the history
)

* add 2 new examples

* finish new examples

* finish new examples pt2

* update new examples with docstrings and improved tests

* add docstrings

* finish docstrings

* make sure that class methods are only using the class attributes to produce their results

* test that the return value is an instance of a custom class

* use closure to check for usage of class attributes

* update property section and quiz

* Expand docstring description of Exercise 4

* finish updating the exercises

* Minor changes

* Stupid metadata fix of the ipython notebook

* Fixing

* Replacing variable l: E741 Ambiguous variable name: `l`

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: edoardob90 <[email protected]>
Co-authored-by: Snowwpanda <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Nov 15, 2024
1 parent 1ce10a4 commit 9240a6d
Show file tree
Hide file tree
Showing 8 changed files with 978 additions and 283 deletions.
802 changes: 558 additions & 244 deletions object_oriented_programming.ipynb

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions tutorial/object_oriented_programming.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,37 @@
class OopQuiz(Quiz):
def __init__(self, title=""):
q1 = Question(
question="Based on what you learned about Python's special methods, which of the following statements is <strong>true</strong>?",
question="Based on what you learned about Python's special methods, which statement best describes the relationship between <i>__str__</i> and <i>__repr__</i>?",
options={
"__repr__ is also used for __str__, but not vice versa.": "Correct! This statement is true.",
"__str__ is also used for __repr__, but not vice versa.": "The opposite is true.",
"__repr__ and __str__ are completely independent.": "__repr__ is also used for __str__, but not vice versa.",
"__repr__ is used as a fallback when __str__ is missing.": "Correct! When __str__ is not defined, Python will use __repr__ instead.",
"__str__ is used as a fallback when __repr__ is missing.": "Think again based on the example we saw earlier.",
"__repr__ and __str__ are independent methods with no relationship to each other.": "There is a relationship between the two methods. Which one could it be?",
},
correct_answer="__repr__ is also used for __str__, but not vice versa.",
correct_answer="__repr__ is used as a fallback when __str__ is missing.",
hint="",
shuffle=True,
)

q2 = Question(
question="Based on what you learned about Python's comparison methods, which of the following statements is <strong>false</strong>?",
options={
"If we implement __gt__, Python will also use it for __lt__": "This statement is true.",
"If we implement __lt__, Python will also use it for __le__": "Correct! This statement is false.",
"If we implement __eq__, Python will also use it for __ne__": "This statement is true.",
"If we implement __gt__, Python will also use it for __lt__": "Wrong! This statement is true because Python is able to cleverly swap the comparison terms.",
"If we implement __lt__, Python will also use it for __le__": "Correct! This statement is false because Python has no knowledge of what equality could mean based just on a comparison.",
"If we implement __eq__, Python will also use it for __ne__": "Wrong! This statement is true because Python is able to cleverly negate the equality comparison.",
},
correct_answer="If we implement __lt__, Python will also use it for __le__",
hint="",
shuffle=True,
)

q3 = Question(
question="Based on what you learned about the @property keyword, which of the following statements is <strong>false</strong>?",
question="Based on what you learned about the <i>@property</i> keyword, which of the following statements is <strong>true</strong>?",
options={
"@property creates attributes that act like methods but can be accessed and assigned as regular attributes.": "This statement is true.",
"@property helps implement attributes that require additional logic or validation when getting or setting their values.": "This statement is true.",
"@property makes code more readable but restricts dynamic attibute behaviour.": "Correct! This statement is false.",
"@property creates attributes that act like methods, which means that they need to be called as regular methods.": "Wrong! This statement is false beacuse we access these attributes as regular ones.",
"@property helps implement attributes that require additional logic or validation when calculating their values.": "Correct! This is how you can make your classes more readable and user-friendly.",
"@property allows to get and set the values of attributes, while applying additional logic in the background.": "Wrong! This statement is false beacuse we are not allowed to directly set the values of these attributes.",
},
correct_answer="@property makes code more readable but restricts dynamic attibute behaviour.",
correct_answer="@property helps implement attributes that require additional logic or validation when calculating their values.",
hint="",
shuffle=True,
)
Expand Down
4 changes: 3 additions & 1 deletion tutorial/tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,9 @@ def test_password_validator2(start: int, end: int, function_to_test) -> None:
# Exercise: Buckets reorganization
#

prio = {l: i for i, l in enumerate(ascii_lowercase + ascii_uppercase, start=1)}
prio = {
letter: i for i, letter in enumerate(ascii_lowercase + ascii_uppercase, start=1)
}
buckets_1, buckets_2 = (read_data(f"buckets_{num}.txt") for num in (1, 2))


Expand Down
8 changes: 5 additions & 3 deletions tutorial/tests/test_functions_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ def hello(name):
def reference_once(allowed_time: int = 15) -> t.Callable:
"""Decorator to run a function at most once"""

class TooSoonError(RuntimeError):
def __init__(self, wait: float):
super().__init__(f"Wait another {wait:.2f} seconds")

def decorator(func: t.Callable) -> t.Callable:
timer = 0.0

Expand All @@ -156,9 +160,7 @@ def wrapper(*args, **kwargs) -> t.Any:
return func(*args, **kwargs)

if (stop := time.perf_counter()) - timer < allowed_time:
raise RuntimeError(
f"Wait another {allowed_time - (stop - timer):.2f} seconds"
)
raise TooSoonError(allowed_time - (stop - timer))

timer = time.perf_counter()

Expand Down
4 changes: 2 additions & 2 deletions tutorial/tests/test_library_scipy.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ def reference_lu():
# 1. TODO: define the matrix a_ref here:
a_ref = np.array([[9, 3, 3], [3, 2, 2], [3, 4, 2]])
# 2. TODO: call the lu function here:
p, l, u = lu(a_ref)
p_matrix, l_matrix, u_matrix = lu(a_ref)

# 3. TODO: return p, l, u matrices in this order here:
return p, l, u
return p_matrix, l_matrix, u_matrix


def test_lu(function_to_test):
Expand Down
Loading

0 comments on commit 9240a6d

Please sign in to comment.