Python, first time using Decimal and quantize - python

I was just wondering if anybody had any input on how to improve this code. My goal is for it to be as pythonic as possible since I'm trying to really learn python well. This program works fine, but if you see anything that you think could be done to improve (not major changes, just basic "Im new to python" stuff) this program please let me know.
#!/usr/bin/python
from decimal import *
print "Welcome to the checkout counter! How many items are you purchasing today?"
numOfItems = int(raw_input())
dictionary = {}
for counter in range(numOfItems):
print "Please enter the name of product", counter + 1
currentProduct = raw_input()
print "And how much does", currentProduct, "cost?"
currentPrice = float(raw_input())
dictionary.update({currentProduct:currentPrice})
print "Your order was:"
subtotal = 0
for key, value in dictionary.iteritems():
subtotal = subtotal + value
stringValue = str(value)
print key, "$" + stringValue
tax = subtotal * .09
total = subtotal + tax
total = Decimal(str(total)).quantize(Decimal('0.01'), rounding = ROUND_DOWN)
stringSubtotal = str(subtotal)
stringTotal = str(total)
print "Your subtotal comes to", "$" + stringSubtotal + ".", " With 9% sales tax, your total is $" + stringTotal + "."
print "Please enter cash amount:"
cash = Decimal(raw_input()).quantize(Decimal('0.01'))
change = cash - total
stringChange = str(change)
print "I owe you back", "$" + stringChange
print "Thank you for shopping with us!"

Call the product dictionary "products" or some similarly descriptive name, instead of just "dictionary"
Generally, if you are iterating over a range, use xrange instead of range for better performance (though it's a very minor nitpick in an app like this)
You can use subtotal = sum(dictionary.itervalues()) to quickly add up all the item prices, without having to use the loop.
You should definitely use Decimal throughout to avoid inaccuracies due to float.
You can use a formatting string like '%.2f' % value (old-style format) or '{:.2f}' .format(value) (new-style format) to print out values with two decimal places.
The tax value should be a constant, so it can be changed easily (it's used in two places, once for the calculation and once for the display).

Updating a dictionary, I would use dict[key] = value, rather than dict.update({key:value})
Instead of concatenating strings, try using format specification. This looks cleaner and saves you having to convert values to strings explicitly.
C-style: "Qty: %d, Price: %f" % (qty, price)
string.format: "Qty: {0}, Price {1}".format(qty, price)

1 to add key-value in a dict, you can use:
dictionary[currentProduct] = currentPrice
but, you don't need a dict in this case, because dict is orderless. You can use a list of tuple.
2 Why not use Decimal(raw_input()), then you can do all the calculation in decimal without using floats.
3 To print the result, you don't need convert values to str first, you can use str.format()

Related

How to eliminate redundancy using a function (def)? [duplicate]

This question already has answers here:
Replacements for switch statement in Python?
(44 answers)
Closed 2 years ago.
I'm building a currency converter and I've pretty much finished the program. However, I am trying to eliminate redundancy by implementing a function or a define block. I've tried a number of things but it does not seem to be working.
My current code is like this:
EUR = 0.83
EGY = 16.22
def currency_converter():
money = total_value
new_value = 0
if currency == 1:
new_value = money*EUR_CON
print("Your total is " + "$" + str(money) + " US Dollars which is " + "e£ " + str(new_value) + " European Euros.")
elif currency == 2:
new_value = money*EGY_CON
print("Your total is " + "$" + str(money) + " US Dollars which is " + "e£ " + str(new_value) + " Egyptian Pounds.")
I want to essentially make the clause under the if/elif block a function. I've tried doing this:
def conversion(EUR_CON,GDP_CON, BRL_CON, EGY_CON, YEN_CON):
new_value = money*conversion()
print("Your total is " + "$" + str(money) + " US Dollars which is " + str(new_value)+ str(conversion)
if currency == 1:
conversion(EURO_CON)
But it's not working. Can someone help?
The correct way to do this is to make a mapping or enum that ties the type of conversion to the associated parameters (in this case, the multiplier and the string name of the target currency). For example, with enum:
from enum import Enum
class Currency(Enum):
EUR = 0.83, "European Euros"
EGY = 16.22, "Egyptian Pounds"
def currency_converter(target_currency):
multiplier, name = target_currency.value # Retrieve value of enum and unpack parts for use
new_value = money * multiplier
print(f"Your total is ${money} US Dollars which is {new_value} {name}")
which then allows you to use it with just:
currency_converter(Currency.EUR) # Convert to euros
To be clear: Using a dict for a similar purpose is perfectly fine as well. Enums mostly just emphasize that there are a fixed, known set of possible conversions, where dicts don't have that idea baked in as thoroughly (adding and removing keys is always a possibility).
I'll note that in real code, functions generally shouldn't rely on receiving non-constant information from globals, nor should they print the results (returning them allows the caller to print, or not print, as they choose) so a better design would be something like:
def convert_usd_to_currency(target_currency, money):
multiplier, _ = target_currency.value # Retrieve value of enum and unpack parts for use
return money * multiplier
possibly with a helper that does the printing (if you really have many places that need to format it the same way):
def print_converted_currency(currency, money):
new_value = convert_usd_to_currency(currency, money)
print(f"Your total is ${money} US Dollars which is {new_value} {currency.name}")
I'll admit to a failure of imagination here; I almost never see a need to factor out the output code itself (each location prints different things based on need), so I'd probably just inline that work in the one place that actually prints it (as opposed to potentially many places that need to perform the conversion).
Put all your conversion rates into a list or dictionary, so you don't need all those if statements.
You don't need so many parameters to the function. Just the currency you're converting to and the amount. The function can then look up all the information related to the currency parameter.
conversion_data = {
'EUR': {'rate': 0.83, 'symbol': '€', 'name': 'European Euros'},
'EGY': {'rate': 16.22, 'symbol': '£', 'name': 'Egyptian Pounds'},
...
}
def conversion(currency, dollars):
new_value = dollars * conversion_data[currency]['rate']
return f"Your total is ${dollars} US dollars which is {conversion_data[currency]['symbol']}{new_value} {conversion_data[currency]['name']}."
print(conversion('EUR', 5))

String Formatting Dollar Sign In Python

So I'm trying to get the dollar sign to appear directly to the left of the digits under the column 'Cost'. I'm having trouble figuring this out and any help is appreciated.
# Question 5
print("\nQuestion 5.")
# Get amount of each type of ticket to be purchased
adultTickets = input("\nHow many adult tickets you want to order: ")
adultCost = int(adultTickets) * 50.5
childTickets = input("How many children (>=10 years old) tickets: ")
childCost = int(childTickets) * 10.5
youngChildTickets = input("How many children (<10 years old) tickets: ")
# Display ticket info
print ("\n{0:<17} {1:>17} {2:>12}".format("Type", "Number of tickets",
"Cost"))
print ("{0:<17} {1:>17}${2:>12.2f}".format("Adult", adultTickets, adultCost))
print ("{0:<17} {1:>17}${2:>12.2f}".format("Children (>=10)", childTickets,
childCost))
print ("{0:<17} {1:>17} {2:>12}".format("Children (<10)", youngChildTickets,
"free"))
#Calculate total cost and total amount of tickets
totalTickets = (int(adultTickets) + int(childTickets) +
int(youngChildTickets))
totalCost = adultCost + childCost
print ("{0:<17} {1:>17}${2:>12.2f}".format("Total", totalTickets, totalCost))
I also want the cost column to be formatted right, which for some reason it isn't when I run the program.
(My output):
Edit: I also can't format the '$' onto the cost, as I have to keep the 2 decimal places in the formatting
If I understand correctly, you want to format a floating point number into a string, and have a dollar sign appear in the output in between the number and the padding that you use to space it out in the string. For example, you want to be able to create these two strings with the same formatting code (just different values):
foo: $1.23
foo: $12.34
Unfortunately, you can't do this with just one string formatting operation. When you apply padding to a number, the padding characters will appear in between the number and any prefixing text, like the dollar signs in your current code. You probably need to format the number in two steps. First make the numbers into strings prefixed with the dollar signs, then format again to insert the dollar strings into the final string with the appropriate padding.
Here's how I'd produce the example strings above:
a = 1.23
b = 12.34
a_dollars = "${:.2f}".format(a) # make strings with leading dollar sign
b_dollars = "${:.2f}".format(b)
a_padded = "foo:{:>8}".format(a_dollars) # insert them into strings with padding
b_padded = "foo:{:>8}".format(b_dollars)
I had the same issue, and I was able to solve it with a string like this:
print("%5d" % month,"%3s"%'$',"%12.2f" % balance,"%4s"%'$',"%11.2f" % interest,"%4s"%'$',"%13.2f" % principal)
It printed this in a nice even table.
Month | Current Balance | Interest Owned | Principal Owned
1 $ 9000.00 $ 90.00 $ 360.00
This indented the $ to the start of each table column, while also leaving enough space for very large figures. It's not ideal though since it would be nice to nest it right next to the dollar number.

How can I output to display $00.00 to the second decimal. Code currently generate $00.0 or/and $00.000000000000000

I can't get code to round to the second decimal
Ive tried changing from str to int and even float?
print(round(GrossPay,2))
#SHORT TERM CALCULATOR
rate_of_pay = (input("what is the partners rate of pay? $"))
#SALARY CALCULATIONS 100% 5 DAY WORK WEEK
salary_weekly = float(rate_of_pay)*40
salary_daily = salary_weekly/5
#HOURLY CALCULATION 66.67% 7 DAY WORK WEEK
hourly_cal = float(rate_of_pay)*40
hourly_weekly = hourly_cal*.6667
hourly_daily = hourly_weekly/7
#SALARIED TOTALS
print ("Salaried WEEKLY = $" + str(salary_weekly))
print ("Salaried DAILY = $" + str(salary_daily))
#HOURLY TOTALS
print ("Hourly WEEKLY = $" + str(hourly_weekly))
print ("Hourly DAILY = $" + str(hourly_daily))
Expecting output to show decimal rounded to the second decimal in every situation
print("{:.2f}".format(number))
You probably want to use
print("${:#.2f}".format(value))
This only works in Python 3 and ensures that the value is always printed with 2 decimals, even if they are 0.
Use the formatted string
print (f'{hourly_daily:.2f}'

How to remove parentheses and comma from printed output

Edit: Apparently I was using python 2. Switching to 3 fixed the issue and now I am getting the proper results without the parentheses/commas. Thanks for the replies - problem solved :D
Beginner at Python and coding in general. Struggling with my first project assignment, but I've gotten so close on my own.
My assignment is to create a code in python that counts the number of coins from a given value i.e. quarters, nickels, dimes, pennies.
My initial code looks like this:
coins=input('Enter amount of change: ')
print("Quarters", coins//25)
coins = coins%25
print("Dimes", coins//10)
coins = coins%10
print("Nickles", coins//5)
coins = coins%5
print('Pennies', coins//1)
Which prompts something like, "Enter amount of change: 86"
('Quarters', 3)
('Dimes', 1)
('Nickles', 0)
('Pennies', 1)
These are the correct values, but my instructor wants it to look like this:
Enter amount of change: 86
Quarters: 3
Dimes: 1
Nickles" 0
Pennies: 1
I can get the colon in there, but how can I remove the parentheses and commas? Thanks
You can use str.format() to produce the required output. For example for quarters:
print('Quarters: {}'.format(coins//25))
This will work in both versions of Python.
The simplest solution I've always used to print values in Python 2, which is the Python version you appear to be using, is the following:
coins=int(input('Enter amount of change: '))
print "Quarters: %i" % (coins//25)
coins = coins%25
print "Dimes: %i" % (coins//10)
coins = coins%10
print "Nickles: %i" % (coins//5)
coins = coins%5
print 'Pennies: %i' % (coins//1)
The % symbol, when used with strings, allows whatever value you want to be printed to be substituted in the string. To substitute multiple values, you separate them with commas. For example:
someInt = 1
someStr = 'print me!'
print "The values are %i and %s" % (someInt, someStr)
This code will substitute in someInt and someStr for %i (used for integers) and %s (used for strings), respectively.
However, the % symbol also functions as the modulus operator, so it does 2 different things when it is being used with strings and when it is being used among two numbers.
Please check :
coins=input('Enter amount of change: ')
print "Quarters:",coins//25
coins = coins%25
print "Dimes:",coins//10
coins = coins%10
print "Nickles:",coins//5
coins = coins%5
print "Pennies:",coins//1
To use the print() syntax on python2 add this to the top of your program:
from __future__ import print_function
otherwise python will interpret the argument to print as a tuple and you'll see ().
I am using Python 3 and the following lines exactly give what your instructor wants:
coins=float(input("Enter amount of change: "))
print("Quarters:", round(coins//25))
coins = coins%25
print("Dimes:", round(coins//10))
coins = coins%10
print("Nickels:", round(coins//5))
coins = coins%5
print("Pennies: %.0f" % coins)
It seems like you are using Python 2. I think you intended to use Python 3 given your use of input() and print() methods, but the code will work in Python 2 by changing print() methods to print keywords. Your code would look like the following in "proper"* Python 2:
coins = input('Enter amount of change: ')
print 'Quarters: ' + str(coins // 25)
coins = coins % 25
print 'Dimes: ' + str(coins // 10)
coins = coins % 10
print 'Nickles: ' + str(coins // 5)
coins = coins % 5
print 'Pennies: ' + str(coins)
Hope this helped!
Footnote: Using % is preferred over using string concatenation, but I still believe that it is easier to read for beginners this way.

Issue with including variables in print function

I have developed a piece of code for school and i have got to the end a run into a final problem, to finish the game i need to print off the end values of the results of the sums carried out and i am having problem including the variable names as inputted by the user, here is the code;
import random
print('Welcome to the game')
char1=input('What is the fist characters name: ')
char2=input('What is the second characters name: ')
char1st=int(input('What is the strength of '+char1))
char1sk=int(input('What is the skill of '+char1))
char2st=int(input('What is the strength of '+char2))
char2sk=int(input('What is the skill of '+char2))
strmod = abs (char2st - char1st) // 5
sklmod = abs (char2sk - char1sk) //5
char1rl=random.randint(1,6)
char2rl=random.randint(1,6)
if char1rl>char2rl:
char1nst=(char1st+strmod)
char1nsk=(char1sk+sklmod)
char2nsk=(char2sk-sklmod)
char2nst=(char2st-strmod)
elif char2rl>char1rl:
char2nst=(char2st+strmod)
char2nsk=(char2sk+sklmod)
char1nsk=(char1sk-sklmod)
char1nst=(char1st-strmod)
else:
print('both rolls where the same, no damage was given or taken')
if char1nst <= 0:
print(str(+char1+' has died'))
elif char2nst <=0:
print(str(+char2+' has died'))
else:
print(+char1( ' now has a strength value of '+char1nst' and a skill value of '+char1nsk'.'))
print(+char2( ' now has a strenght value of '+char2nst' and a skill value of '+char2nsk'.'))
I wrote the bit at the end in the hope that it would print the end values but i get a syntax error ?! and don't have clue why it is happening. Can someone please help me edit the last four lines so it will print in the format of:
Bob now has a strength value of 4 and a skill value of 7
I have used my method before but its not working this time so if someone could point out where i went wrong and how to amend this problem that would be great !!!!
You have concatenation operators (+) in places where you don't need them (at the beginning of print() and you don't have them in places where you do need them (after the variable in of '+char1nsk'.'). That's what's causing the syntax error.
You might consider string formatting instead of string concatenation:
print "%s now has a strength value of %d and a skill value of %d" % (char1, char1nst, char1nsk)
You are trying to use the + operator without anything to append:
print(str(+char2+' has died'))
You don't need the str nor the + operators there, just use multiple arguments to the print() function:
if char1nst <= 0:
print(char1, 'has died'))
elif char2nst <=0:
print(char2, 'has died'))
else:
print(char1, 'now has a strength value of', char1nst, 'and a skill value of', str(char1nsk) + '.'))
print(char2, 'now has a strength value of', char2nst, 'and a skill value of', str(char2nsk) + '.'))
Only in the last two lines do I use str() and + to avoid a space between the value an the . full stop.
You could, instead, use string formatting with the str.format() method to get a more readable string formatting option for those last 2 lines:
template = '{} now has a strength value of {} and a skill value of {}.'
print(template.format(char1, char1nst, char1nsk))
print(template.format(char2, char2nst, char2nsk))
Because the text is the same for both lines, you can re-use a template string here.
Try removing the + int the beginning of the print statements. Change it to this:
print char1 +' has died'
print char2 +' has died'
else:
print(char1 +' now has a strength value of '+char1nst+' and a skill value of '+char1nsk+'.')
print(char2 +' now has a strenght value of '+char2nst+' and a skill value of '+char2nsk+'.')
well since your using python3 why not use .format?
insert {} into your string where you want a value, then call the format() method on that string with the values you want in the correct order.
else:
temp = "{} now has a strength value of {} and a skill value of {}."
print(temp.format(char1, char1nst, char1nsk))
print(temp.format(char2, char2nst, char2nsk))
cleanest soluton if you ask me.

Categories

Resources