From 10762426b633194d5878e933ac35ecbd0dde868d Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Sun, 14 Jul 2024 09:03:51 +0100 Subject: [PATCH 1/3] Add hints This should help make the lab more approachable --- README.md | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9a2e5a1..7377222 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,24 @@ Invalid choice - try again Enter choice(1/2/3/4): 5 ``` +
+ +Hint + +The `else` statement can be used to run code when the `if` (or related `elif`) blocks aren't executed: + +```python +x = 4 +if x > 5: + print("x is greater than 5") +else: + print("x is less than or equal to 5") +``` + +Also, you can use the `continue` statement to return to the top of the `while` loop, and execute it again. + +
+ ### Rather than entering numbers for each of the operations, use the mathematical symbol ("+" for addition etc) ``` @@ -34,6 +52,16 @@ Select operation: Enter choice: + ``` +
+ +Hint + +The choices are currently numbers (`if choice == "1"`). + +Reusing the `choice` in the `print` statement, or the calculation itself, might reduce duplication - but it might be at the cost of readability. + +
+ ### Add support for operating on decimal values ``` @@ -48,6 +76,25 @@ Enter second number: 3.5 2.5 + 3.5 = 6 ``` +
+ +Hint + +Python has 2 main numeric types. An `int` represents a whole number, whilst a `float` _can_ also include a fractional component (but don't have to). + +```python +>>> type(1) + +>>> type(1.5) + +>>> type(1.0) + +``` + +Where in the code is the user's input converted to an `int`? + +
+ ### When prompted for a number, if someone enters something which isn't a number, show an error message and ask for the value again ``` @@ -62,6 +109,23 @@ Enter first number: no Enter first number: no ``` +
+ +Hint + +Sometimes, it's easier to ask for forgiveness than permission. Rather than trying to check whether something is a number, try doing something with it, and complain if it goes wrong. + +```python +try: + num = int("no") +except ValueError: + print("'no' is not a number.") +``` + +`int` (and `float`) _raises_ a `ValueError` if it receives a string it can't convert. `try` and `except` allow us to _catch_ this _exception_ and do something about it, without our code crashing. + +
+ Extension: If someone gives an invalid value for the second number, don't ask for the first number again. ### Add a "Power of" choice, which raises the first number to the power of the second. @@ -96,6 +160,14 @@ Enter first number: 9 sqrt 9 = 3 ``` +
+ +Hint + +We know which choice the user wants (`choice`) before we prompt them for each number. Maybe the second number (`num2`) is only asked for when the choice uses it? + +
+ ### If the calculation fails, show a sensible message ``` @@ -109,10 +181,42 @@ Select operation: Enter choice: / Enter first number: 3 Enter second number: 0 -3 / 0 failed: ZeroDivisionError: float division by zero +3 / 0 failed: ZeroDivisionError: division by zero Enter choice: ``` +
+ +Hint + +Exceptions have a type and a message. To get the exception as a variable, use `as`: + +```python +try: + divide(1, 0) +except Exception as e: + print(type(e)) # "ZeroDivisionError" + print(str(e)) # "division by zero" +``` + +You can also handle specific exceptions. `Exception` can be used to handle all exceptions. + +```python +try: + divide(1, 0) +except ZeroDivisionError: + print("You can't divide by zero!") +except ValueError as e: + print("Were both arguments numbers?") +except Exception as e: + print("Something else happened!") + print(type(e)) + print(str(e)) +``` + +
+ + ### Let the user enter the entire equation at once ``` @@ -128,6 +232,28 @@ Available operations: = 5 ``` + +
+ +Hint + +You can split a string by using the `split` method: + +```python3 +>>> "2 + 3".split(" ") +["2", "+", "3"] +``` + +This gives you a list, and you can retrieve specific values from using `[0]` (the first entry in a list is at position 0): + +```python3 +>>> args = "2 + 3".split(" ") +>>> args[1] +"+" +``` + +
+ ### Support "[Reverse Polish](https://www-stone.ch.cam.ac.uk/documentation/rrf/rpn.html)" notation, where the operator comes after the numbers ``` @@ -144,3 +270,28 @@ Available operations: ``` This should work in addition to normal (infix) notation. + +
+ +Hint + +Try finding where the operator is in the equation: + +```python3 +>>> args = "2 + 3".split(" ") +>>> try: +... int(args[2]) +... except ValueError: +... print("The last item isn't a number") +``` + +If you try and retrieve an item which doesn't exist, you'll receive an `IndexError`: + +```python3 +>>> args[4] +Traceback (most recent call last): + File "", line 1, in +IndexError: list index out of range +``` + +
From 058417a5b88ad554d9c2f80f5ffdf848f9473927 Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Sun, 14 Jul 2024 09:04:45 +0100 Subject: [PATCH 2/3] Add a small exercise about control flow --- README.md | 34 ++++++++++++++++++++++++++++++++++ calc.py | 2 ++ 2 files changed, 36 insertions(+) diff --git a/README.md b/README.md index 7377222..615c7f2 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,40 @@ Whilst you can complete the tasks in any order, they start easier and get harder Each task is presented with an example output. This is merely an example - feel free to write it however you wish. +### List the operations again after each calculation + +``` +Select operation. +1.Add +2.Subtract +3.Multiply +4.Divide +Enter choice(1/2/3/4): 1 +Enter first number: 1 +Enter second number: 1 +1 + 1 = 2 +Let's do next calculation? (yes/no): yes + +Select operation. +1.Add +2.Subtract +3.Multiply +4.Divide +Enter choice(1/2/3/4): +``` + +
+ +Hint + +`while True` means "run this code forever". This is what keeps re-running our code over and over again. + +Python uses indenting to identify when blocks of code start or end. The `while` loop acts on everything indented 1 level further in than it. + +If the user doesn't want to do another calculation, `break` will "break" out of the loop, stop running the code in the loop, and run the rest of the program. + +
+ ### Show a message when the user enters an invalid operation ``` diff --git a/calc.py b/calc.py index d0ddbe0..4e99235 100644 --- a/calc.py +++ b/calc.py @@ -46,3 +46,5 @@ def divide(x, y): next_calculation = input("Let's do next calculation? (yes/no): ") if next_calculation == "no": break + +print("Thank you.") From de1e8b914ce0d38d8114dbbf319e7d6d98733fe2 Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Sun, 14 Jul 2024 09:07:14 +0100 Subject: [PATCH 3/3] Document the hints --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 615c7f2..174e72c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Whilst you can complete the tasks in any order, they start easier and get harder Each task is presented with an example output. This is merely an example - feel free to write it however you wish. +Below each task are "hints", which you can use to help you in the right direction if you need them. They're collapsed by default, but just click them to show them. See if you can complete the task without using the hints. + ### List the operations again after each calculation ```