Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialjack f
Full Stack JavaScript Techdegree Student 377 PointsCan I make my code more concise?
Wherever possible, I'd like to:
- Reduce the number of parameters of some functions
- Break the functions up into smaller logical units
Questions:
- Does create_order() do too much?
- confirm_purchase() and purchase_tickets() both have the same parameters. Is it possible to avoid this?
Something unique I did was create bitcoin.py in order to get the current exchange rate of bitcoin in real time.
(I didn't follow along with the tutorial at all). If you want to run the code (without the line numbers,) I also have a Github repo here
main.py
1 import sys
2 import bitcoin
3
4 tickets_stock = 200
5 USD_TICKET_PRICE = 14
6 event = 'Monty Python Q&A Session'
7 bitcoin_exchange_rate = bitcoin.bitcoin_price()
8 name = input('What is your name?: ').title()
9
10
11 def print_welcome():
12 if tickets_stock == 0:
13 sys.exit('Sorry we\'re all out of tickets!')
14
15 print(f'\nHello {name}!')
16 print('\n----------------------\n')
17 print('Welcome to the CLI Ticketing System')
18 print('----------------------\n')
19
20 print(f'We are currently selling tickets for the {event}')
21 print(f'Each ticket costs: ${USD_TICKET_PRICE}\n')
22
23
24 def show_ticket_stock():
25 if tickets_stock == 1:
26 print('We\'re down to our last ticket!')
27 elif 1 < tickets_stock < 100:
28 print(f'Buy now! We only have {tickets_stock} tickets remaining!\n')
29 elif tickets_stock > 100:
30 print(f'There are currently {tickets_stock} tickets remaining.')
31
32
33 def ticket_quantity_request():
34 while True:
35 try:
36 tickets_request = int(input('How many tickets would you like to purchase?: '))
37 while tickets_request > tickets_stock:
38 print(f'Sorry, we only have {tickets_stock} tickets in stock! Try again...\n')
39 tickets_request = int(input('How many tickets would you like to purchase?: '))
40 return tickets_request
41 except ValueError:
42 print('\nOops! That was an invalid number. Try again...')
43
44
45 def calculate_purchase_cost(tickets):
46 return tickets * USD_TICKET_PRICE
47
48
49 def usd_to_bitcoin(cost):
50 return cost / bitcoin_exchange_rate
51
52
53 def ask_for_payment_method():
54 while True:
55 try:
56 payment_method = input('Will you be paying using a Credit Card or by Bitcoin? (c/b): ')
57 if payment_method == 'c':
58 print('\nSelected payment method: Credit Card\n')
59 return 'usd'
60 elif payment_method == 'b':
61 print('\nSelected payment method: Bitcoin\n')
62 return 'bitcoin'
63 else:
64 print(f'Hmm... I didn\'t understand {payment_method}')
65 except BaseException as e:
66 print('\nHmm, there was an error: ' + str(e))
67
68
69 def payment_method_symbol(payment_method):
70 if payment_method == 'bitcoin':
71 return '฿'
72 elif payment_method == 'usd':
73 return '$'
74
75
76 def cost_string(symbol, cost):
77 return f'{symbol}{cost}'
78
79
80 def cost_string_after_considering_payment_method(tickets, payment_method):
81 usd_cost = calculate_purchase_cost(tickets)
82 currency_symbol = payment_method_symbol(payment_method)
83 if payment_method == 'usd':
84 return cost_string(currency_symbol, usd_cost)
85 elif payment_method == 'bitcoin':
86 cost_in_bitcoin = usd_to_bitcoin(usd_cost)
87 return cost_string(currency_symbol, cost_in_bitcoin)
88
89
90 def confirm_purchase(tickets, string):
91 while True:
92 response = input(f'You are purchasing {tickets} tickets for {string}. '
93 f'\nIs this order correct? (y/n): ')
94 if response == 'y':
95 purchase_tickets(tickets, string)
96 return tickets
97 elif response == 'n':
98 print(f'Cancelling order...')
99 break
100 elif response == ('exit' or 'e' or 'c' or 'cancel'):
101 print('Your order was canceled')
102 sys.exit()
103 else:
104 print(f'\nHmm, I don\'t recognize the option "{response}"...\n')
105
106
107 def purchase_tickets(tickets, string):
108 response = input('Purchase tickets (p): ')
109 if response == 'p':
110 print('\nPurchase complete...')
111
112 print(f'\n\nPurchase Confirmation for {name}:')
113 print('---------------')
114 print(f'Thank you {name}! Your payment of {string} was received.')
115 print('\n***')
116 print(f'Congratulations! You now have {tickets} tickets to the "{event}"')
117 print('***')
118 sys.exit()
119 else:
120 print('goodbye...')
121 sys.exit()
122
123
124 def create_order():
125 ticket_quantity = tick et_quantity_request()
126 payment_method = ask_for_payment_method()
127 show_cost = cost_string_after_considering_payment_method(ticket_quantity, payment_method)
128 confirm_purchase(ticket_quantity, show_cost)
129 purchase_tickets(ticket_quantity, show_cost)
130 return
131
132
133 def main():
134 print_welcome()
135 show_ticket_stock()
136 create_order()
137
138
139 if __name__ == '__main__':
140 main()
141
bitcoin.py
1 import json
2
3
4 def bitcoin_price():
5 try:
6 import urllib.request as urllib2
7 except ImportError:
8 raise ImportError('There was a problem importing urllib2')
9
10 url = "http://api.coindesk.com/v1/bpi/currentprice/EUR.json"
11
12 json_url = urllib2.urlopen(url)
13 json_object = json.load(json_url)
14
15 exchange_rate = json_object['bpi']['USD']['rate']
16
17 return float(exchange_rate.replace(',', ''))
18
I would be grateful for any improvements you are able to provide.
1 Answer
Jeff Muday
Treehouse Moderator 28,722 PointsNice work! Your program was written in a very clear manner and easy to follow.
Your create_order()
doesn't need to be broken down any further. I would not worry about duplicated parameter passing in this scenario since you are adhering to the best practices of the functional programming paradigm.
I don't think I would change anything.
But the stubborn old project manager I had when I was first starting out was insistent on best practices. Two of the software engineering principles he insisted upon were to "minimize exit points" and to "have meaningful return values from functions and programs."
In that spirit, you could possibly create a single exit point from main()
. Currently, your program can sys.exit()
in two different ways confirm_purchase()
and purchase_tickets()
.
Another thing would be to add an argument to your sys.exit()
indicating successful completion of the program like a sys.exit(0)
if tickets were sold, and sys.exit(1)
if the user canceled the sale.
(By convention, zero is used when termination is normal and 1 is canceled or abnormal termination)
https://stackoverflow.com/questions/9426045/difference-between-exit0-and-exit1-in-python
Keep up the good work!