Scope issue with nested functions - python

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

Related

How do I sum given data in written file in python

My code runs almost correctly. The program needs to take in a country name, software/hardware/accessory sales, and then give the average for each category per country, total sales for each category, and overall total sales. If the users opt to enter a second, third, etc country, the averages and total must all be added together to find each calculation. My code currently calculates all of those things, but it does it for each country separately and it doesn't correctly count the number of countries added. I don't know why or how to fix it, please help!
def request_countryname():
country_name = input('Please enter the country\'s name: ')
while len(country_name) < 2:
print('Name must be at least two chracters')
country_name = input('Please enter the country\'s name: ')
return country_name
def request_sales(product_type, country_name):
sales = float(input('Please enter the total sales for ' + product_type + ' in ' + country_name + ": "))
while sales == type(str) or sales < 0:
print('Sales must be a non-negative numeric input')
sales = float(input('Please enter the total sales for', product_type, 'in', country_name))
return sales
def request_data(sales_data):
sales_data = open('sales_data.txt', 'w')
records = 0
add_country = True
while True:
records += 1
country_name = request_countryname()
soft_sales = request_sales('software', country_name)
hard_sales = request_sales('hardware', country_name)
acc_sales = request_sales('accessories', country_name)
sales_data.write(f'{country_name}\n{soft_sales}\n{hard_sales}\n{acc_sales}\n')
add_country = input('Do you want to add another country? (Enter y/Y for Yes, any other key to stop): ')
if add_country == 'y' or add_country == 'Y':
records += 1
request_data("sales_data.txt")
analyze_data("sales_data.txt")
else:
print(records, 'record(s) successfully added to the file.')
print('----------------------------------------------\n')
sales_data.close()
return sales_data
def analyze_data(sales_data):
sales_data = open ('sales_data.txt', 'r')
software_sales = []
hardware_sales = []
accessory_sales = []
read_file = sales_data.readline()
while read_file != '':
soft_sales = sales_data.readline()
hard_sales = sales_data.readline()
acc_sales = sales_data.readline()
software_sales.append(float(soft_sales))
hardware_sales.append(float(hard_sales))
accessory_sales.append(float(acc_sales))
read_file = sales_data.readline().rstrip('\n')
soft_average= sum(software_sales)/len(software_sales)
hard_average = sum(hardware_sales)/len(hardware_sales)
acc_average = sum(accessory_sales)/len(accessory_sales)
total_soft = sum(software_sales)
total_hard = sum(hardware_sales)
total_acc = sum(accessory_sales)
total_sales = float(total_soft + total_hard + total_acc)
print('Average software sales per country: $' + format(soft_average, ',.2f'))
print('Average hardware sales per country: $' + format(hard_average, ',.2f'))
print('Average accessory sales per country: $' + format(acc_average, ',.2f'))
print('')
print('Total software sales: $' + format(soft_average, ',.2f'))
print('Total hardware sales: $' + format(hard_average, ',.2f'))
print('Total accessory sales: $' + format(acc_average, ',.2f'))
print('')
print('Total sales: $' + format(total_sales, ',.2f'))
sales_data.close
def main():
request_data("sales_data.txt")
analyze_data("sales_data.txt")
main()
Edit: my professor said the problem was in the request_data function, specifically the "while True" part because I need to specify what is true, I just don't know what.
I'm going to try to answer your question, but also give you some refactoring pointers that may be helpful:
def request_country_name():
country_name = ""
while len(country_name) < 2:
print('Name must be at least two characters')
country_name = input('Please enter the country\'s name: ')
return country_name
def request_sales(product_type, country_name):
sales = ""
while sales == type(str) or sales < 0:
print('Sales must be a non-negative numeric input')
try:
sales = float(input(f"Please enter the total sales for {product_type} in {country_name}: "))
except:
pass
return sales
def read_record(record):
header = {'country_name': str,'soft_sales': float,'hard_sales': float,'acc_sales': float}
str_dict = dict(zip(list(header.keys()), record.replace("\n", "").split(",")))
return {k:header[k](v) for k,v in str_dict.items()}
def request_data(sales_data_file="sales_data.csv"):
records = 0
add_country = True
while True:
records += 1
country_name = request_country_name()
soft_sales = request_sales('software', country_name)
hard_sales = request_sales('hardware', country_name)
acc_sales = request_sales('accessories', country_name)
with open(sales_data_file, 'w') as writer:
writer.write(f'{country_name},{soft_sales},{hard_sales},{acc_sales}\n')
add_country = input('Do you want to add another country? (Enter y/n): ').upper()
if add_country == 'Y':
analyze_data(sales_data_file)
else:
print(F"{records} record(s) successfully added to the file.\n----------------------------------------------\n")
break
def analyze_data(sales_data_file="sales_data.csv"):
latest_country_records = {}
with open(sales_data_file) as reader:
for line in reader.readlines():
data = read_record(line)
latest_country_records[data['country']] = data
total_soft = sum([v['soft_sales'] for v in latest_country_records.values()])
soft_average= total_soft/len(latest_country_records)
total_hard = sum([v['hard_sales'] for v in latest_country_records.values()])
hard_average = total_hard/len(latest_country_records)
total_acc = sum([v['acc_sales'] for v in latest_country_records.values()])
acc_average = total_acc/len(latest_country_records)
total_sales = total_soft + total_hard + total_acc
print('Average software sales per country: $' + format(soft_average, ',.2f'))
print('Average hardware sales per country: $' + format(hard_average, ',.2f'))
print('Average accessory sales per country: $' + format(acc_average, ',.2f'))
print('')
print('Total software sales: $' + format(total_soft, ',.2f'))
print('Total hardware sales: $' + format(total_hard, ',.2f'))
print('Total accessory sales: $' + format(total_acc, ',.2f'))
print('')
print('Total sales: $' + format(total_sales, ',.2f'))
def main():
request_data("sales_data.txt")
analyze_data("sales_data.txt")
if __name__ == "__main__":
main()
Alright, so after some refactoring -- I think your biggest issue was you weren't handling the file handlers well (I replaced with context managers) which led to some odd structuring -- ie. your "request_data" function was being called recursively (by itself) in an unnecessary way.
Some other things to note, in your final print out you were printing the avg in place of the totals -- also you avg & total calculations overlapped a bit (reuse the total and calc it first).
Last note, and one worth keeping front of mind -- 9 times out of 10 there's an existing, established data structure -- lean on those. In this case, csv is your friend, in others json will be helpful.
Storing the data in different rows leads to unneeded complexity, and if possible should be avoided.
FWIW -- I haven't run/tested this code so there may be a few errors

Calculate the total of tickets and give a discount to student. There is a problem with function of the calculation the total and loops

Ticket sales. Calculate the total, based on the number of half price and full price tickets. If the user is a student, give a 50 cent discount for each ticket. Ask user to input number of child tickets, number of adult tickets, and if the person is a student (y/n). Keep asking until user enters a 0 and a 0
FULL_PRICE = 10.00
HALF_PRICE = FULL_PRICE % 2
giveDiscount = True
def calculatePrice(nHalfPriceTix, nFullPriceTix, giveDiscount):
if giveDiscount:
total = (nHalfPriceTix * HALF_PRICE) + (nFullPriceTix * FULL_PRICE) - .5
else:
total = (nHalfPriceTix * HALF_PRICE) + (nFullPriceTix * FULL_PRICE)
return total
while True:
print()
nChildTickets = input('How many child tickets do you want? ')
nChildTickets = int(nChildTickets)
nAdultTickets = input('How many adult tickets do you want? ')
nAdultTickets = int(nAdultTickets)
if (nChildTickets == 0) or (nAdultTickets == 0):
break
yesOrNo = input('Are you a student (y/n)? ')
if yesOrNo.lower() == 'y':
isStudent = True
else:
isStudent = False
thisTotal = calculatePrice(nChildTickets, nAdultTickets)
print('Your total is $' + thisTotal)
print()
totalSales = totalSales + thisTotal
print('Total of all sales $', totalSales)
Also to add on, this:
print('Your total is $' + thisTotal)
should be:
print('Your total is $' + str(thisTotal))
since the '+' operator in print() can only accept strings(not a float).
Or you could change the + to a ,.
calculatePrice function requires 3 arguments and got only two:
thisTotal = calculatePrice(nChildTickets, nAdultTickets)
so i think for that to work you need to pass isStudent because you didnt use it
thisTotal = calculatePrice(nChildTickets, nAdultTickets,isStudent)

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 go about fixing this block of code?

The code below is supposed to output the following if you choose employee
Do you wish to enter data for an (E)mployee, a (S)alesperson, or would you like to (Q)uit?: e
Enter the name of the employee: (employee name)
Enter (employee name) hourly pay rate: (pay rate)
Enter (employee name) hours worked: (hours worked ```
Employee data:
Employee name: (employee name)
Employee hourly pay: (hourly pay)
Hours worked: (hours worked)
Pay: (pay)
That is if you choose the to enter data for an employee ^^^
Here is the following output if you would like the choose the following data for a Salesperson
Do you wish to enter data for an (E)mployee, a (S)alesperson, or would you like to (Q)uit?: s
Enter the name of the employee: (employee name)
Enter (employee name) hourly pay rate: (hourly pay)
Enter the number of hours worked by (employee name): (hours worked)
Enter the amount of sales made by (employee name): (sales made)
Enter the commission percentage that will be earned by (employee name): (commission percentage)
Salesperson data:
Employee name: (employee name)
Employee hourly pay: (hourly pay)
Hours worked: (hours worked)
Sales: (sales made)
Commission percentage: (commission percent)
Pay: (pay)
Here is the entire block of code that is executing all of this. Keep in mind that this has to be done using classes and polymorphism.
class Employee:
def __init__(self, hours_worked, hourly_rate):
self.__hours_worked = 0
self.__hourly_rate = 0
def set_hours_worked(self, hours_worked):
self.__hours_worked = hours_worked
def get_hours_worked(self):
return self.__hours_worked
def set_hourly_rate(self, hourly_rate):
self.__hourly_rate = hourly_rate
def get_hourly_rate(self):
return self.__hourly_rate
def calc_pay(self):
return self.__hourly_rate * self.__hours_worked
def __str_(self):
print()
string1 = 'Employee data: ' + '\n' + 'Employee name: ' + employee_name + '\n' + 'Employee hourly pay rate: ' + employee_pay + '\n' + 'Hours worked: ' + employee_hours + '\n' + 'Pay: ' + employee_pay
class Salesman(Employee):
def __init__(self, weekly_sales, commission, hours_worked, hourly_rate):
Employee.__init__(self, hours_worked, hourly_rate)
self.__weekly_sales = 0
self.__commission = 0
def set_weekly_sales(self, weekly_sales):
self.__weekly_sales = weekly_sales
def get_weekly_sales(self):
return self.__weekly_sales
def set_commission(self, commission):
self.__commission = commission
def get_commission(self):
return self.__commission
def calc_pay(self):
return Employee.calc_pay(self) + (self.__weekly_sales * self.__commission)
def __str__(self):
print()
string2 = 'Salesperson data: ' + '\n' + 'Employee name: ' + salesperson_name + '\n' + 'Employee hourly pay rate: ' + str(
salesperson_pay) + '\n' + 'Hours worked: ' + salesperson_hours + '\n' + 'Sales: ' + salesperson_sales + '\n' + 'Commission percentage: ' + str(
salesperson_commission) + '\n' + 'Pay: ' + str(salesperson_pay)
go_on = 'y'
while go_on == 'y':
input1 = input('Do you wish to enter data for an (E)mployee, a (S)alesperson, or would you like to (Q)uit?: ')
if input1 == 'e' or 'E':
employee_name = input('Enter the name of the employee: ')
employee_pay = input('Enter ' + employee_name + ' hourly pay rate: ')
employee_hours = input('Enter the number of hours worked by ' + employee_name + ': ')
employee_pay_rate = employee_pay * int(employee_hours)
employee = Employee(employee_name, employee_pay, employee_hours, employee_pay_rate)
print(employee)
if input1 == 's' or 'S':
salesperson_name = input('Enter the name of the employee: ')
salesperson_pay = float(input('Enter ' + salesperson_name + ' hourly pay rate: '))
salesperson_hours = input('Enter the number of hours worked by ' + salesperson_name + ': ')
salesperson_sales = input('Enter the amount of sales made by ' + salesperson_name + ': ')
salesperson_commission = float(input('Enter the commission percentage that will be earned by ' + salesperson_name + ': '))
salesperson = Salesman(salesperson_pay, salesperson_hours, salesperson_sales, salesperson_commission)
print(salesperson)
else:
go_on = 'n'
I am sure I got mostly everything right but I'm running into a couple problems and I don't know how to fix them.
Error: you are passing 5 arguments in the while loop to Employee with self included.
When taking input as a string from the user, use raw_input instead
of input.
input1 == "e" or "E" is always true. Do input1 == "e" or input1 == "E"
This way you are making use of the while loop to add as many users as needed.
And also some additional points:
You have a base class Employee whose constructor or init accepts (self, hours_worked, hourly_rate)
recommended: (self, name, hours_worked, hourly_rate)
In class Salesman's __init__ method, try to maintain the order of arguments passed where the parent class Employees arguments come first.
recommended: `class Salesman(Employee):
def __init__(self, name, hours_worked, hourly rate, weekly_sales, commission):
Employee.__init__(self, name, hours_worked, hourly_rate)
self.__weekly_sales = 0
self.__commission = 0`

NameError: global name 'user_cent' is not defined

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

Categories