NameError: global name 'user_cent' is not defined - python

I'm writing a simple coin counter program and get the 'global name not defined error' after inputting all weights of the coins. I didn't get this error before when my calculation block was just within the main() function without defining a function for itself. I however want two separate functions so I can create a while loop within main() to allow the user to repeat the program without restarting it. Help? I've had a look on here at other questions and it seems to be about the variables created in main being local and not able to be accessed from subsequent functions but I'm slightly confused! Here is my code:
import time
import math
def intro():
print "----- " + "Welcome to CoinCounter" + " -----\n"
def main():
print "Please enter all weights in Grams\n"
user_cent = float(raw_input("Enter the total weight of cents: "))
user_nickel = float(raw_input("Enter the total weight of nickels: "))
user_dime = float(raw_input("Enter the total weight of dimes: "))
user_quarter = float(raw_input("Enter the total weight of quarters: "))
user_halfdollar = float(raw_input("Enter the total weight of half dollars: "))
calculation()
def calculation():
num_cent = user_cent / 2.640
num_nickel = user_nickel / 5.975
num_dime = user_dime / 2.268
num_quarter = user_quarter / 5.670
num_halfdollar = user_halfdollar / 11.340
wrap_cent = num_cent / 132
wrap_nickel = num_nickel / 199
wrap_dime = num_dime / 113
wrap_quarter = num_quarter / 226
wrap_halfdollar = num_halfdollar / 453.6
value_cent = (wrap_cent * 0.5)
value_nickel = (wrap_nickel * 2.0)
value_dime = (wrap_dime * 5.0)
value_quarter = (wrap_quarter * 10.0)
value_halfdollar = (wrap_halfdollar * 10.0)
time.sleep(1)
total_value = value_cent + value_nickel + value_dime + value_quarter + value_halfdollar
results()
def results():
print "\n--- RESULTS --- "
print "\nYou need:" \
"\n\n %s cent wrappers\n" \
" %s nickel wrappers\n" \
" %s dime wrappers\n" \
" %s quarter wrappers\n" \
" %s half dollar wrappers\n" \
"\nand the value of this is: " \
% ("%.0f" % math.ceil(wrap_cent), "%.0f" % math.ceil(wrap_nickel), "%.0f" % math.ceil(wrap_dime), "%.0f" % math.ceil(wrap_quarter), "%.0f" % math.ceil(wrap_halfdollar))
print "\n" + " $%s worth of cents\n $%s worth of nickels" % ("%.2f" % value_cent, "%.2f" % value_nickel)
print " $%s worth of dimes\n $%s worth of quarters" % ("%.2f" % value_dime, "%.2f" % value_quarter)
print " $%s worth of half dollars\n" % ("%.2f" % value_halfdollar)
print " Your total amount is:\n" + " --- " + "$%s" % ("%.2f" % total_value) + " ---"
intro()
main()

Unless you explicitly declare variables modified in a function as global variables, they default to local. This means that the user_cent variable is local to the main function, and thus not accessible by the calculation function. This could be fixed by adding a global user_cent, user_nickle, user_dime, user_quarter, user_halfdollar line to the beginning of the main function, but global variables are not needed here. You could pass the weights as arguments to the calculation function/

At this stage in your learning, you should assume that using global variables is the wrong approach. Once you have more experience, it will be easier to see when using global may be appropriate (which is much less often than you might think). Until then, pass arguments to functions and return values.
The below is not great code, but it's enough of an improvement for one answer.
import time
import math
def intro():
print "----- " + "Welcome to CoinCounter" + " -----\n"
def main():
print "Please enter all weights in Grams\n"
user_cent = float(raw_input("Enter the total weight of cents: "))
user_nickel = float(raw_input("Enter the total weight of nickels: "))
user_dime = float(raw_input("Enter the total weight of dimes: "))
user_quarter = float(raw_input("Enter the total weight of quarters: "))
user_halfdollar = float(raw_input("Enter the total weight of half dollars: "))
calculation([user_cent, user_nickel, user_dime, user_quarter, user_halfdollar])
def calculation(coins):
cents, nickels, dimes, quarters, halfdollars
num_cent = cents / 2.640
num_nickel = nickels / 5.975
num_dime = dimes / 2.268
num_quarter = quarters / 5.670
num_halfdollar = halfdollars / 11.340
wrap_cent = num_cent / 132
wrap_nickel = num_nickel / 199
wrap_dime = num_dime / 113
wrap_quarter = num_quarter / 226
wrap_halfdollar = num_halfdollar / 453.6
value_cent = (wrap_cent * 0.5)
value_nickel = (wrap_nickel * 2.0)
value_dime = (wrap_dime * 5.0)
value_quarter = (wrap_quarter * 10.0)
value_halfdollar = (wrap_halfdollar * 10.0)
time.sleep(1)
total_value = value_cent + value_nickel + value_dime + value_quarter + value_halfdollar
results([wrap_cent, wrap_nickel, wrap_dime, wrap_quarter, wrap_halfdollar],
[value_cent, value_nickel, value_dime, value_quarter, value_halfdollar],
total_value)
def results(wrappers, values, total):
print "\n--- RESULTS --- "
print "\nYou need:" \
"\n\n %.0f cent wrappers\n" \
" %.0f nickel wrappers\n" \
" %.0f dime wrappers\n" \
" %.0f quarter wrappers\n" \
" %.0f half dollar wrappers\n" \
"\nand the value of this is: " \
% tuple(map(math.ceil, wrappers))
print "\n" + " $%.2f worth of cents\n $%.2f worth of nickels" % (values[0], values[1])
print " $%.2f worth of dimes\n $%.2f worth of quarters" % (values[2], values[3])
print " $%.2f worth of half dollars\n" % (values[4],)
print " Your total amount is:\n --- $%2.f ---" % (total,)
intro()
main()

Related

TypeError: can only concatenate list (not "str") to list : Python

I was trying to bubble sort the temperature array but i am getting this kind of error.. Someone please help me fix this :)
Here's the code :
print("")
print("")
days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thrusday", "Friday", "Saturday"]
temperature = []
highest = float(0.0)
lowest = float(100.0)
total = float(0.0)
for i in range(7):
inp = round(float(input("Please enter the temperature for " + days[i] + " in Celcus: ")),1)
temperature.append(inp)
print("")
print("")
print("You entered these Temperatures in Celsius and Fahrenheit.")
print("")
print("")
for j in range(len(temperature)):
def bubble_sort(tem):
for a in range(len(tem)):
for b in range(len(tem)-1):
if(tem[b]>tem[b+1]):
temp=tem[b]
tem[b]=tem[b+1]
tem[b+1]=temp
return tem
arr = []
arr.append(temperature[j])
Fahrenheit = round(((temperature[j] * 1.8) + 32),1)
total = total + temperature[j]
print(bubble_sort(arr) + " C° is " + str(Fahrenheit) + " F°" )
print("--------------------")
avg = round(total / len(temperature),1)
print("High Temp: " + str(max(temperature)) + "C°, Low Temp: " + str(min(temperature)) + " C° Average Temp: " + str(avg) + " C°")
I am not getting what wrong is with this code ..
The error is pretty explicit: the list is bubble_sort(arr) and the str is " C° is "
You can't concatenate them at bubble_sort(arr) + " C° is ", you'd need to wrap the list into str
The nicest is just to use the fact that print allows multiple values to be given
print(bubble_sort(arr), "C° is", Fahrenheit, "F°")
print("High Temp:", max(temperature), "C°, Low Temp:",
min(temperature), "C° Average Temp:", avg, "C°")
Now, you're not sorting anything as there is only ONE value in arr, just sort once before the loop, then show the Fahrenheit value
arr = bubble_sort(temperature)
for value in arr:
fahrenheit = round(((value * 1.8) + 32), 1)
print(value, "C° is", fahrenheit, "F°")
avg = round(sum(temperature) / len(temperature), 1)
print("High Temp:", max(temperature), "C°, Low Temp:",
min(temperature), "C° Average Temp:", avg, "C°")
the defectiv line is
print(bubble_sort(arr) + " C° is " + str(Fahrenheit) + " F°" )
since you are using the "+" operator on a list and a string
in order to fix it try converting the list (that you get from calling "bubble_sort(arr)" to a string )
like this
print(''.join(str(e) for e in bubble_sort(arr)) + " C° is " + str(Fahrenheit) + " F°")

Scope issue with nested functions

I get an unexpected indent error in def calculte_interest_on_savings(savings)? The variable savings got defined above on the exact same line...
def print_balance():
balance = 1000
print("Your balance is " + str(balance))
def deduct(amount):
print("Your new balance is " + str(balance - amount))
savings = balance-amount
deduct(500)
def calculte_interest_on_savings(savings):
print("You will gain interest on: " + str (savings))
calculte_interest_on_savings(savings)
print_balance()
I would write this way
def print_balance(balance):
print("Your balance is " + str(balance))
def deduct(amount,balance):
print("Your new balance is " + str(balance - amount))
savings = balance-amount
return savings
def calculte_interest_on_savings(savings):
print("You will gain interest on: " + str(savings))
balance = 1000
print_balance(balance)
savings=deduct(500,balance)
calculte_interest_on_savings(savings)
print_balance(balance)
There is no reason to nest these functions.
def print_balance():
balance = 1000
print("Your balance is " + str(balance))
savings = deduct(balance, 500)
calculate_interest_on_savings(savings)
def deduct(balance, amount):
print("Your new balance is " + str(balance - amount))
savings = balance - amount
return savings
def calculate_interest_on_savings(savings):
print("You will gain interest on: " + str(savings))
if __name__ == '__main__':
print_balance()

TypeError while using an function with an input as an argument

When I tested this code and typed a number,
cost = int(input("Enter cost of meal: "))
def get_cost():
return cost
def compute_tip(cost):
tip = (cost*0.18)+cost
return tip
def compute_tax(cost):
tax = (cost*0.825)+0.825
return tax
def main():
print("Cost: $" + str(get_cost()))
print("Tip: $" + str(compute_tip()))
print("Tax: $" + str(compute_tax()))
print("Total: $" + str(get_cost() + compute_tip() + compute_tax()))
main()
it showed that I have an error:
Traceback (most recent call last):
File "HW05B.py", line 20, in <module>
main()
File "HW05B.py", line 16, in main
print("Tip: $" + str(compute_tip()))
TypeError: compute_tip() takes exactly 1 argument (0 given)
Could anyone give me ideas on how to pass the error? Thanks!
Assign a variable in the main method to capture the value you get from get_cost :
int(input("Enter cost of meal: "))
def get_cost():
return cost
def compute_tip(cost):
tip = (cost*0.18)+cost
return tip
def compute_tax(cost):
tax = (cost*0.825)+0.825
return tax
def main():
cost = get_cost()
tip = compute_tip(cost)
tax = compute_tax(cost)
print("Cost: $" + str(cost))
print("Tip: $" + str(tip))
print("Tax: $" + str(tax))
print("Total: $" + str(cost + tip + tax))
main()
There is an issue with the way you have defined the functions. In compute_tip(cost)and in
compute_tax(cost) you have passed an argument "cost". So you program expects you to pass an argument whenever you define these functions.
Your function get_cost() does not use an argument and hence works fine.
So any of these will work well:
cost = int(input("Enter cost of meal: "))
def get_cost():
return cost
def compute_tip(cost):
tip = (cost*0.18)+cost
return tip
def compute_tax(cost):
tax = (cost*0.825)+0.825
return tax
def main():
print("Cost: $" + str(get_cost()))
print("Tip: $" + str(compute_tip(cost)))
print("Tax: $" + str(compute_tax(cost)))
print("Total: $" + str(get_cost() + compute_tip(cost) + compute_tax(cost)))
main()
Or,
cost = int(input("Enter cost of meal: "))
def get_cost():
return cost
def compute_tip():
tip = (cost*0.18)+cost
return tip
def compute_tax():
tax = (cost*0.825)+0.825
return tax
def main():
print("Cost: $" + str(get_cost()))
print("Tip: $" + str(compute_tip()))
print("Tax: $" + str(compute_tax()))
print("Total: $" + str(get_cost() + compute_tip() + compute_tax()))
main()
Thanks for asking.
Have a great day.

How would I work around this invalid literal for int() with base 10 error?

import math
# The standard gravitational parameter for the sun
mu = 1.327 * math.pow(10, 20)
class Planet:
def __init__(self, name, radius, moons, orbital_radius):
self.name = name
self.radius = radius
self.moons = moons
self.orbital_radius = orbital_radius
def collide(self):
self.moons = self.moons + 1
return self.moons
def volume(Planet):
v = (4 / 3) * math.pi * math.pow(Planet.radius, 3)
return str(v)
def surface(Planet):
area = 4 * math.pi * math.pow(Planet.radius, 2)
return str(area)
def physical(Planet):
if Planet.moons == 1:
Planet.moons = str(Planet.moons) + " moon"
else:
Planet.moons = str(Planet.moons) + " moons"
return (Planet.name + " has a volume of " + volume(Planet) + " cubic km, a surface area of " + surface(Planet) + " sq. km, and " + Planet.moons)
def dynamic(Planet):
period = 2 * math.pi * Planet.orbital_radius * math.sqrt(Planet.orbital_radius / mu)
return (Planet.name + " has a year of approximately " + str(period // (60 * 60 * 24)) + " days")
Earth = Planet('Earth', 6371, 1, 1.496 * math.pow(10, 11))
Jupiter = Planet('Jupiter', 69911, 79, 7.786 * math.pow(10, 11))
print(physical(Earth))
print(physical(Jupiter))
print(dynamic(Earth))
print(dynamic(Jupiter))
print(Earth.collide())
I understand that self.moons is turned into a string due to the physical function but how would I go about in turning into an integer again. It doesn't seem possible as an integer and string is stored as its value that's why I'm getting the error message ValueError: invalid literal for int() with base 10: '1 moon' when I attempt to print(Earth.collide())
Just partition the string on a space and take the first part:
int(self.moon.partition(" ")[0])
You can also use str.split() but partition is a little faster for the 'only need to split once' case.
The better approach is to not set the .moons attribute to a string. Keep it an integer, there is no need to replace it just to format a nice string with information:
def physical(Planet):
if Planet.moons == 1:
moons = str(Planet.moons) + " moon"
else:
moons = str(Planet.moons) + " moons"
return (Planet.name + " has a volume of " + volume(Planet) + " cubic km, a surface area of " + surface(Planet) + " sq. km, and " + moons)
You may want to look at formatted string literals or the format string syntax:
def physical(Planet):
moons = f"{Planet.moons} moon"
if Planet.moons != 1:
moons += 's'
return (
f"{Planet.name} has a volume of {volume(Planet)} cubic km, a surface "
f"area of {surface(Planet)} sq. km, and {moons}"
)
Either way, by using a local variable moons to contain the formatted number of moons value, you don't alter the Planet.moons value so don't have to worry about how to go back to it being an integer again.
I would recommend, to stick with a local/private variable in def physical(Planet), because it is not used anywhere else and just a format to a value.
def physical(Planet):
if Planet.moons == 1:
_planet_moons = str(Planet.moons) + " moon"
else:
_planet_moons = str(Planet.moons) + " moons"
return (Planet.name + " has a volume of " + volume(Planet) + " cubic km, a surface area of " + surface(Planet) + " sq. km, and " + _planet_moons)
This prevents you from convering the value forth and back.

Conditional statement printing values twice python

So I am testing my script in which i am passing two values to compare. It goes through two conditional statements. I have carried out some debugging and it prints out the same expression twice which is "Current value is in range". It first prints it out from the first loop and then from the second loop. I am not sure why my code is doing that. It should only print that out once and get out of the else statement and not go in to the second else statement which it is currently doing. What is that I am doing wrong to stop this.
def compare_sizes(previous_size, current_size):
subtract_f1_f2 = int(current_size - previous_size)
range_num = 0.4
range_previous_day = int(previous_size * range_num)
if subtract_f1_f2 > 0 and range_previous_day > 0 and subtract_f1_f2 >= range_previous_day:
whole_percent = subtract_f1_f2 / previous_size * 100
print (human_bytes(previous_size) +" -> " + human_bytes(current_size) + " " +
"+" + str(whole_percent) + " % bigger" + "\n")
return
else:
print("Current Value Is In Range")
if subtract_f1_f2 <0 and subtract_f1_f2 <= range_previous_day:
whole_percent = abs(subtract_f1_f2 / previous_size * 100)
print (human_bytes(previous_size) + " -> " + human_bytes(current_size) + " " + str(
whole_percent) + " % smaller" + "\n")
else:
print("Current Value Is In Range")
result = compare_sizes(1000,1400)# 40% Bigger
result = compare_sizes(1000,1399)# In Range
# result = compare_sizes(1000,599)

Categories