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

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))

Related

Change value of variable INSIDE a variable python [duplicate]

This question already has answers here:
How can I select a variable by (string) name?
(5 answers)
Closed 8 months ago.
I want to change the value of a variable that's inside another variable, this is the code I have so far:
person1tokens = 0
person2tokens = 0
token_price = 5
accounts = ["person1tokens","person2tokens"]
def add_tokens(person,amount):
if person in accounts:
cost = amount*token_price
print("You need to pay %d$" % (cost))
payment = int(input("Payment? "))
if payment != cost:
print("Please enter the right amount next time, nothing changed")
else:
--Help here--, change value of a the in the function specified account to <account> += amount
print("Added " + str(amount) + " tokens to account " + str(person) + ", your current balance is " + str(eval(person)"."))
else:
print("fail")
I basically want to change the value of person1tokens(for example) without knowing beforehand that I want to change that value, and I want to change that value where it says --Help here--.
But the problem is that it is inside the person variable and I don't know how to get the program to "unpack" it from there.
So for example if the user does as follows:
add_tokens("person1tokens",5)
You need to pay 25$
Payment? 25
Added 25 tokens to account person1tokens, your current balance is 25.
Any ideas?
If I'm understanding you correctly here, you want to be able to change the value of either person1tokens or person2tokens without knowing which will be changed beforehand (please correct me if I'm wrong). One way I can think to do this would be using a dictionary rather than storing their values in their own separate variables, and then changing the values based off of that.
accounts = {'person1tokens': 0,
'person2tokens': 0}
def add_tokens(person, amount):
if person in accounts:
cost = amount*5
payment = int(input("Payment? "))
if payment != cost:
print("Please enter the right amount next time, nothing changed")
else:
accounts[person] = accounts[person] + cost
print("Added " + str(amount) + " tokens to account " + str(person) + ", your current balance is " + str(accounts[person]) + ".")
else:
return False
This would allow you to have a large amount of people and simply refer to them by name. The one downside to this for you is that you won't be able to refer to the variables, but you can still reference the persons balance by doing accounts['nameofperson']
Hope this helped!

I need suggestions to fix my python code's bug that involves trying to find watt_hours and amp_hours?

I am very new to programming in python and in general. I am currently trying to practice writing a program for an upcoming project with solar power. I need to be able to enter volts, watts, and amps to calculate amp-hours and watt-hours while having one unknown variable. I would like some suggestions to make my code better and to fix the bugs I have.
I use a -1 in my code when it asks for input for amps, volts, and watts as a way to show an unknown variable. When I know watts and volts and I don't know amps the program runs fine to calculate watt_hours and amp_hours. However, when I enter a -1 for an unknown variable for watts or volts my amp_hours and watt_hours become negative, which is not a real value. I could use suggestions on making this simple program run smoother without any bugs. Any suggestions help! I got stuck on what to do next, but I would like to be able to see how more experienced programmers would approach this slight issue.
FYI: This program is used for a solar build for a campervan:
**My code:**
#defining watts amps volts, amps-hours, and watt-hours.
def watts_calc(x, y):
return amps * volts
def amps_calc(x, y):
return watts/volts
def volts_calc(x, y):
return watts / amps
def amp_hour(x, y):
return amps * hours
def watt_hour(x, y):
return watts * hours
#How many appliances are used in the Van
appliance_number = int(input("How many appliances are you trying to use? "))
#Setting up conditional arguments for while loop
condition = 1
while condition <= appliance_number:
#Defining varibles
amps = float(input("How many Amps does the device use: "))
volts = float(input("How many Volts does the device use: "))
watts = float(input("How many Watts is used: "))
hours = float(input("How many hours of use? "))
print("\n")
#a if/elif statement that takes input of watts, volts, amps in
#to calculate the missing variable indicated by -1
if amps == -1:
print("Amps are: " + str(amps_calc(watts, volts)) + "A")
elif volts == -1:
print("Volts are: " + str(volts_calc(watts, amps)) + "v")
elif watts == -1:
print("Watts are: " + str(watts_calc(amps, hours)) + "W")
else:
print("Invalid Input")
print("Watt-hours for appliance " + str(condition) + ": " + str(watt_hour(watts, hours)))
print("Amp-hours for appliance " + str(condition) + ": " + str(amps_calc(watts, volts) * hours) + "\n")
condition += 1
The problem is that where you have a -1 for an unknown value, you are just printing out what the value should be, but you are not actually updating it for the subsequent calculations. Save the result in the relevant variable, and it should be fine.
if amps == -1:
amps = amps_calc(watts, volts)
print("Amps are: " + str(amps) + "A")
elif volts == -1:
volts = volts_calc(watts, amps)
print("Volts are: " + str(volts) + "v")
elif watts == -1:
watts = watts_calc(amps, hours)
print("Watts are: " + str(watts) + "W")
Someone else's answer spotted an additional problem, which while not the main source of your issue, also needs correcting. That answer has for some reason since been deleted, so I'll mention it here myself. In your functions you are ignoring the x and y parameters in the function and are instead using variables from the outer scope. Whilst you happen to get away with that in this case, it clearly needs fixing also. For example,
def watts_calc(x, y):
return amps * volts
should be:
def watts_calc(amps, volts):
return amps * volts
Then amps and volts will be function parameters rather than variables used from the outer scope. (You could also use x and y but the meanings are then less clear.)
first of all you might want to store those numbers in variables in the methods, you could instead of having them input a number, have them put in a char for each metric they want to use, or one char for the metric they want to find, then just have list of those chars and use for loops, or you could experiment with lamdba instead of using standars syntax for thos functions
It seems like the only way you would have a negative value is if you have multiple inputs that are negative. However, it seems like you wish to only allow one variable to be unknown. Let me know if this isn't the case.
There are a few ways to approach this. One way is to reformat your code to ask for which calculation the user wishes to do and then prompt for values accordingly.
Another would be to use assert within your functions or to check whether one of the values is negative with an if statement.
You may also wish to combine both of these.
Let me know if you have any follow-up questions.

TypeError: cannot convert int to str implicitely

Im having trouble fixing this code can someone help me I don't know how to fix the 'sale' function help please and thank you
def main():
#store introduction
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print("Welcome to the Movie Store!")
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
#user input on budget
budget = (input("What is your budget?"))
print("Your budget is " + budget + "$.")
# declaring variables
sale = (200 - int(budget))
# selection statements to determine subtotal
if (200 > int(budget)):
print("If you spend $" + sale + " you'll qualify for a gift!")
else:
print("You qualify for a free gift!")
print("We recommend our all time best seller Marvels Black Panther!")
main()
Use f-strings for variable substitution (there are also many many other ways):
print(f"Your budget is {budget}$.")
print(f"If you spend ${sale} you'll qualify for a gift!")
In your code currently, you are trying to add the string "Your budget is" to the integer budget, and python doesn't know how to do that. An alternative is to cast the variable to a string explicitly:
print("Your budget is " + str(budget) + "$.")
Or use formatting:
print("Your budget is %s$." % (budget,))
Your variable sale is an integer, which must be converted to a string before your print statement will work.
Do this
if (200 > int(budget)):
print("If you spend $" + str(sale) + " you'll qualify for a gift!")
else:
print("You qualify for a free gift!")
The str() function converts the sale variable to a string so it can be joined with the + operators and printed to console.

Replacing Iteration with Recursion Python [duplicate]

This question already has answers here:
Is this function recursive even though it doesn't call itself?
(3 answers)
Closed 5 years ago.
I'm just starting to learn about recursion for an EdX course, and I've written an iterative function to calculate the remaining balance after paying the minimum required payment for 12 months.
I was able to easily do it with iteration, but I can't seem to wrap my head around the recursive way.
Please point me in the right direction.
Here is my iterative function
def remaining_balance_iter(balance,annualInterestRate, monthlyPaymentRate ):
'''
This code will take any balance and annual interest rate and calculate the
balance after one year of making the minimum payments
'''
month = 1
monthly_interest_rate = annualInterestRate/12.0
while month <= 12:
minimum_monthly_payment = monthlyPaymentRate * balance
monthly_unpaid_balance = balance - minimum_monthly_payment
balance = monthly_unpaid_balance + monthly_interest_rate*monthly_unpaid_balance
print( "Month {} Remaining balance: ".format(month) + str(round(balance,2)))
month += 1
print ("Remaining balance " + str(round(balance,2)))
I've made an attempt at a recursive function, but it needs work, and I need tutoring haha
def remaining_balance_recur(balance,annualInterestRate, monthlyPaymentRate, month ):
'''
This code will take any balance and annual interest rate and calculate the
balance after one year of making the minimum payments
'''
month = 1
monthly_interest_rate = annualInterestRate/12.0
while month <= 12:
minimum_monthly_payment = monthlyPaymentRate * balance
monthly_unpaid_balance = balance - minimum_monthly_payment
interest = monthly_interest_rate*monthly_unpaid_balance
balance = remaining_balance_recur(monthly_unpaid_balance, annualInterestRate, monthlyPaymentRate, month + 1) + interest
print ("Remaining balance " + str(round(balance,2)))
The best way I've found to deal with recursion is to start by specifying a base case. What is the condition that tells you when you've finished your method? In your code, it looks like you run your method until `month > 12', so your base case would be:
if month > 12:
return 1 # 1 for the purpose of explanation
Your return value for your base case is some base value of your function. What would your script return if your month was 12? That's the value you would return.
Next is the hard part. You have to figure out what variable is being modified by subsequent calls to your method. I'm not exactly sure what your code is intended to do, but it looks like you have a few calculations on some variables. When you use recursion, it's almost as if you're saving the state of the current method call you are executing while you go and retrieve the value you need for your statement. (e.g. a_num = 1 + recurse(n - 1) - you need the value of recurse(n - 1) before you can continue with this statement. This is only an example, though). Look for the variable that is affected by your previous iterations and try to make that recursive. In your situation, it looks like balance is that variable:
balance = balance + remaining_balance_recur(annualInterestRate, monthlyPaymentRate, month + 1)
return balance
When you write a recursive method, you always need to return some value at the end of the method, so the statement that called the method actually gets a value. Here's a short, useless example:
def recurse(n)
if n == 0 # BASE CASE
return 1
some_sum = 0
some_sum += recurse(n - 1) # I need the value from recurse(n - 1)
return some_sum # This method was called somewhere, so it needs to return
Try to figure out a recursive solution for your code from these hints. I'm sorry, recursion is very hard to explain especially over SO. Youtube vids and Google would also be a big help to understand recursion in general. Hope this gave you some ideas.
By putting "month = 1" before the while statement, you are resetting it so that while month <= 12 will run forever. This creates a "RecursionError: maximum recursion depth exceeded in comparison."
The output of your function is currently "NoneType" because its output is a print statement rather than returning an int or a float. This produces a "TypeError" because you have tried to add a float (the interest rate) to a NoneType (the printed statement) in your recursion.

Python, first time using Decimal and quantize

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()

Categories

Resources