Skip to content

Commit 0454f3c

Browse files
committed
Chapter 8
1 parent 02332a5 commit 0454f3c

15 files changed

Lines changed: 281 additions & 0 deletions

Ch8/address_book.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
friend_emails = {
2+
"Anne": "[email protected]",
3+
"Brent": "[email protected]",
4+
5+
"David": "[email protected]",
6+
7+
"Jane": "[email protected]",
8+
"Kevin": "[email protected]",
9+
"Robert": "[email protected]"
10+
}
11+
12+
13+
def lookup_email(name):
14+
try:
15+
return friend_emails[name]
16+
except KeyError as e:
17+
print(f"<No entry for friend {e}>")
18+
19+
20+
name = input("Enter name to look up: ")
21+
email = lookup_email(name)
22+
print(f"Email: {email}")

Ch8/average.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
def average(number_string):
2+
total = 0
3+
skip = 0
4+
values = 0
5+
for n in number_string.split():
6+
values += 1
7+
try:
8+
total += float(n)
9+
except ValueError:
10+
skip += 1
11+
if skip == values:
12+
raise ValueError("No valid numbers provided.")
13+
elif skip:
14+
print(f"<!> Skipped {skip} invalid values.")
15+
16+
return total / values
17+
18+
19+
while True:
20+
try:
21+
line = input("Enter numbers (space delimiated):\n ")
22+
avg = average(line)
23+
print(avg)
24+
except ValueError:
25+
print("No valid numbers provided.")

Ch8/average_calculator.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from multiprocessing.sharedctypes import Value
2+
3+
4+
class AverageCalculator:
5+
6+
def __init__(self):
7+
self.total = 0
8+
self.count = 0
9+
10+
def __call__(self, *values):
11+
if values:
12+
for value in values:
13+
self.total += float(value)
14+
self.count += 1
15+
return self.total / self.count
16+
17+
18+
average = AverageCalculator()
19+
values = input("Enter scores, separated by spaces:\n ").split()
20+
try:
21+
print(f"Aviage is {average(*values)}")
22+
except ZeroDivisionError:
23+
print("ERROR: No values provided.")
24+
except (ValueError, UnicodeError):
25+
print("ERROR: All inputs should be numeric.")

Ch8/average_file.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from multiprocessing.sharedctypes import Value
2+
3+
4+
def average_file(path):
5+
file = open(path, 'r')
6+
7+
try:
8+
numbers = [float(n) for n in file.readlines()]
9+
except ValueError as e:
10+
raise ValueError("File contains non-numeric values.") from e
11+
else:
12+
try:
13+
return sum(numbers) / len(numbers)
14+
except ZeroDivisionError as e:
15+
raise ValueError("Empty file.") from e
16+
finally:
17+
print("Closing file.")
18+
file.close()
19+
20+
21+
print(average_file('numbers_good.txt'))
22+
# print(average_file('numbers_bad.txt'))
23+
# print(average_file('numbers_empty.txt'))
24+
# print(average_file('nonexistant.txt'))

Ch8/average_string.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import math
2+
3+
import math
4+
5+
6+
def average_string(number_string):
7+
try:
8+
numbers = [float(n) for n in number_string.split()]
9+
except ValueError:
10+
total = math.nan
11+
values = 1
12+
else:
13+
total = sum(numbers)
14+
values = len(numbers)
15+
16+
try:
17+
average = total / values
18+
except ZeroDivisionError:
19+
average = math.inf
20+
21+
return average
22+
23+
while True:
24+
number_string = input("Enter space-delimited list of numbers:\n ")
25+
print(average_string(number_string))

Ch8/calculator.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import logging
2+
from operator import add, sub, mul, truediv
3+
import sys
4+
5+
logging.basicConfig(filename='log.txt', level=logging.INFO)
6+
7+
8+
def calculator(a, b, op):
9+
a = float(a)
10+
b = float(b)
11+
if op == '+':
12+
return add(a, b)
13+
elif op == '-':
14+
return sub(a, b)
15+
elif op == '*':
16+
return mul(a, b)
17+
elif op == '/':
18+
return truediv(a, b)
19+
else:
20+
raise NotImplementedError(f"No operator {op}")
21+
22+
23+
print("""CALCULATOR
24+
Use postfix notation.
25+
Ctrl+C or Ctrl+D to quit.
26+
""")
27+
28+
while True:
29+
try:
30+
equation = input(" ").split()
31+
result = calculator(*equation)
32+
print(result)
33+
except NotImplementedError as e:
34+
print("<!> Invalid operator.")
35+
logging.info(e)
36+
except ValueError as e:
37+
print("<!> Expected format: <A> <B> <OP>")
38+
logging.info(e)
39+
except TypeError as e:
40+
print("<!> Wrong number of arguments. Use: <A> <B> <OP>")
41+
logging.info(e)
42+
except ZeroDivisionError as e:
43+
print("<!> Cannot divide by zero.")
44+
logging.info(e)
45+
except (KeyboardInterrupt, EOFError):
46+
print("\nGoodbye.")
47+
sys.exit(0)
48+
except Exception as e:
49+
logging.exception(e)
50+
raise

Ch8/diaper_antipattern.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
try:
2+
some_scary_function()
3+
except:
4+
print("An error occurred. Moving on!")

Ch8/landmarks.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from cgitb import lookup
2+
3+
4+
cities = {
5+
"SEATTLE": "WASHINGTON, USA",
6+
"PORTLAND": "OREGON, USA",
7+
"BOSTON": "MASSACHUSETTS, USA",
8+
}
9+
10+
landmarks = {
11+
"SPACE NEEDLE": "SEATTLE",
12+
"LIBERTY SHIP MEMORIAL": "PORTLAND",
13+
"ALAMO": "SAN ANTONIO",
14+
}
15+
16+
17+
def lookup_landmark(landmark):
18+
landmark = landmark.upper()
19+
try:
20+
city = landmarks[landmark]
21+
state = cities[city]
22+
except KeyError as e:
23+
raise KeyError("Landmark not found.") from e
24+
print(f"{landmark} is in {city}, {state}")
25+
26+
27+
lookup_landmark("space needle")
28+
lookup_landmark("alamo")
29+
lookup_landmark("golden gate bridge")

Ch8/log.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
INFO:root:could not convert string to float: '+'
2+
INFO:root:calculator() takes 3 positional arguments but 5 were given
3+
INFO:root:calculator() missing 1 required positional argument: 'op'
4+
INFO:root:float division by zero
5+
INFO:root:No operator @

Ch8/no_escape.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
def greet():
2+
name = input("What's your name? ")
3+
print(f"Hello, {name}.")
4+
5+
6+
while True:
7+
try:
8+
greet()
9+
break
10+
except Exception:
11+
print("Error caught")

0 commit comments

Comments
 (0)