Why is my function not getting called properly? - python

I'm writing a program that will greet somebody (given name) and then ask them how many hours they worked and how much their hourly pay is. The program runs but is not spitting back the correct math. I'm getting this for my answer... you earned<function wage at 0x00EA9540>
I have already tried calling payment but not getting an answer with that either.
def greet(greeting):
name = input("Hi, whats your name?")
return greeting + name
print(greet ("Hey "))
hourly = input("How much is your hourly wage?")
hours = input("How many hours did you work this week?")
def wage(hourly, hours):
if hours > 40:
payment = 40 * hourly
payment = payment + hourly * (hours-40) * 1.5
return payment
else:
return hours * hourly
print("you earned" + str(wage))

You missed the parameters to the wage function.
in your case, it just prints the memory address of the function wage...
you need to change the print call with the correct parameters to the wage function:
print("you earned" + str(wage(hourly, hours)))

You need to call the wage function with the parameters:
print("you earned" + str(wage(hourly, hours)))
Otherwise you are simply printing the string representation of the wage function object, and that doesn't really make much sense.

Related

'NoneType' object has no attribute 'format' python string

I wrote a program in python to find compound interest (more like copied). This program was written in python 2 and I am having a problem on the last line .format(years).
I need to know what I can do with this code, and how to write it properly in Python 3. Also with the {} part in the last line. Should I change it to %s? The error says:
"AttributeError: 'NoneType' object has no attribute 'format'".
My code looks like this :
# Estimated yearly interest
print ("How many years will you be saving ? ")
years = int(input("Enter the number of years : "))
print("How much money is currently in your account ? ")
principal = float(input("Enter current amount in account : "))
print("How much money do you plan on investing monthly ? ")
monthly_invest = float(input("Monthly invest : "))
print("What do you estimate the interest of this yearly investment would be ? ")
interest = (float(input("Enter the interest in decimal numbers (10% = 0.1) : ")))
print(' ')
monthly_invest = monthly_invest * 12
final_amount = 0
for i in range(0, years ):
if final_amount == 0:
final_amount = principal
final_amount = (final_amount + monthly_invest) * (1 + interest)
print("This is how much money you will have after {} years: ").format(years) + str(final_amount)
I find it a bit of a shame that no one recommended f-strings. There are only available since Python 3.6 but they are quite powerful, easy to use and the recommended string formatting option in PEP 498 (unless I'm mistaken).
If you want to get serious about python and work with other people I really recommend reading up on best practices, in this case, f-strings.
Solution using f-strings:
print(f"This is how much money you will have after {years} years: {final_amount}")
Change
print("This is how much money you will have after {} years: ").format(years) + str(final_amount)
to
print("This is how much money you will have after {} years: ".format(years)) + str(final_amount)
format() is a method of the string class. You're using it on the print() function which is of NoneType, hence the error.
You can do a normal string concatenation like this :
Print("This is how much money you will have after " + format(years) + " years: " +str(final_amount)
Or if you wish to keep the same format you can do this
print("This is how much money you will have after {} years: ".format(years) + str(final_amount))
A very basic solution would be to change the last line to:
print("This is how much money you will have after {} years:".format(years), str(round(final_amount,2)))
That will do the trick for you
You could also use Numpy's financial functions
For $1000 invested monthly for 10 years at annual rate of 4%:
>>> import numpy as np
>>> np.fv(.04/12, 10*12, -1000, 0)
147249.8047254786
With an initial principal of $100,000:
>>> np.fv(.04/12, 10*12, -1000, -100000)
296333.07296730485

Python - Passing variables through functions

I am about a week into Python. I have looked at various other questions regarding this, and have grown fairly frustrated that my attempts to implement those suggestions are falling flat.
I have tried a few means of passing variables through, based on things I have read. For example (this isn't necessarily representative of a coherent attempt... I have tried many variations and have had to walk back to get code worth posting):
def verify_nums():
globhours = hours
globrate = rate
try:
globhours = float(globhours)
globrate = float(globrate)
return globhours,globrate
except:
print("You must provide numbers")
def calc():
globhours = globhours
globrate = globrate
if globhours > 40:
base = 40 * globrate
ot = (globhours - 40) * (globrate * 1.5)
pay = base + ot
print(pay)
else:
pay = globrate * globhours
print(pay)
hours = input("Enter hours worked: ")
rate = input("Enter hourly rate: ")
verify_nums()
calc()
I am supremely confused on how to transfer the hours and rate variables over to the calc() function.
I eventually figured out I could just merge these into one function...
def paycalc(hours,rate):
etc.
etc.
hours = input("Enter hours: ")
hours = input("Enter hours: ")
paycalc(hours,rate)
But for the sake of learning, I really want to get this global/local thing figured out.
Thanks for the help!
You seem to be trying to get Python to guess which functions are supposed to be global and which local based on their names. Python doesn't do that. If you assign to a variable in a function, and you want that assignment to be global, you need a global statement at the top of the function:
def verify_nums():
global globhours
global blograte
globhours = hours
globrate = rate
# ...
Also, globhours = globhours doesn't do anything useful—and, in fact, it causes a problem. If you global globhours in that function as well, the statement is meaningless. Without that, you're creating a local variable, and assigning it… the value of that local variable that doesn't exist yet.
Anyway, if you add the right global declarations to all of your functions, they will work, but it won't be a great design.
You really don't need any global variables here. If you think about values rather than variables, everything gets a lot easier.
Your verify_nums function needs to work on two values. So just pass those values in as parameters. And it needs to return two values—that's easy, you already did that part.
Now the caller has to store those two values that it returned, so it can pass them to the calc function. Which can also take two values as parameters.
Putting that all together:
def verify_nums(hours, rate):
try:
numhours = float(hours)
numrate = float(rate)
return numhours, numrate
except:
print("You must provide numbers")
def calc(hours, rate):
if hours > 40:
base = 40 * rate
ot = (hours - 40) * (rate * 1.5)
pay = base + ot
print(pay)
else:
pay = rate * hours
print(pay)
globhours = input("Enter hours worked: ")
globrate = input("Enter hourly rate: ")
hours, rate = verify_nums(globhours, globrate)
calc(hours, rate)
One problem left: what happens if there's an error with the user's input? Inside verify_nums, you handle the error with an except:, then you print a message and do nothing. That means you return None. So, when the caller tries to do hours, rate = None, it's going to get an error, which you're not handling. And you can't just carry on without values. What can you do?
More generally "return a pair of numbers, or return None" is a confusing contract for a function to fulfill. How do you use that function? With a whole lot of ugly type-checking. But "return a pair of numbers, or raise an exception" is a perfectly good contract. How do you use that function? With a simple try.
That's why it's better to put the exception handling in exactly the right place where you can deal with it. You want to skip calling calc if there's an error, so the except has to be where you call calc.
def verify_nums(hours, rate):
numhours = float(hours)
numrate = float(rate)
return numhours, numrate
def calc(hours, rate):
if hours > 40:
base = 40 * rate
ot = (hours - 40) * (rate * 1.5)
pay = base + ot
print(pay)
else:
pay = rate * hours
print(pay)
try:
globhours = input("Enter hours worked: ")
globrate = input("Enter hourly rate: ")
hours, rate = verify_nums(globhours, globrate)
except ValueError:
print("You must provide numbers")
else:
calc(hours, rate)
Another improvement you might want to consider: Have calc return the pay, instead of printing it, and make the caller print the value it returns.

Calling a function that's inside another function from a function

To be more specific, I want to call the function get_hours_worked from inside
calc_gross_pay. I realize that another way to do this is to just pass arguments into calc_gross_pay, but I was wondering if what I was trying to do is possible. I have a feeling it's not. Thanks for any help.
def main():
#
print("This employee's gross pay for two weeks is:",calc_gross_pay())
def get_input():
def get_hours_worked():
#get_hours_worked
x = float(input("How many hours worked in this two week period? "))
return x
def get_hourly_rate():
#get_hourly_rate()
y = float(input("What is the hourly pay rate for this employee? "))
return y
def calc_gross_pay():
#
gross = get_input(get_hours_worked) * get_input(get_hourly_rate)
return gross
main()
Here's a reorganized version of your code. Rather than defining get_hours_worked and get_hourly_rate inside get_input we define them as separate functions that call get_input.
def get_input(prompt):
return float(input(prompt))
def get_hours_worked():
return get_input("How many hours worked in this two week period? ")
def get_hourly_rate():
return get_input("What is the hourly pay rate for this employee? ")
def calc_gross_pay():
return get_hours_worked() * get_hourly_rate()
def main():
print("This employee's gross pay for two weeks is:", calc_gross_pay())
main()
demo
How many hours worked in this two week period? 50
What is the hourly pay rate for this employee? 20.00
This employee's gross pay for two weeks is: 1000.0
As PM 2Ring pointed out, its better to change the hierarchy itself. But in case you want the same still, proceed as follows :
def get_input():
def get_hours_worked():
x = float(input("How many hours worked in this two week period? "))
return x
def get_hourly_rate():
y = float(input("What is the hourly pay rate for this employee? "))
return y
return get_hours_worked, get_hourly_rate # IMP
def calc_gross_pay():
call_worked, call_rate = get_input() # get the functions
gross = call_worked() * call_rate() # call them
return gross
def main():
print("This employee's gross pay for two weeks is:",calc_gross_pay())
#How many hours worked in this two week period? 3
#What is the hourly pay rate for this employee? 4
#This employee's gross pay for two weeks is: 12.0
main()

How to give an error msg based on user input in my program?

So I've written an Electric Bill Calculator in Python. The great news is that it works! However, I need to make it work better. When asked how many hours per day, the user can type in 25, or any other number they want. Obviously there isn't 25 hours in a day. I've tried a few things but I cannot get it to work correctly.
I've tried something like:
hours = input("How many hours per day? ")
if hours > 24:
print("Don't be silly, theres not more than 24 hours in a day ")
else:
main()
What I'm trying to do, is make the program display an error msg, if they enter more than 24 hours, and if they do, then skip to the bottom code that asks if they want to try another calculation. And if they enter 24 hours or less, then continue the program with no error msg. I've spent about 2 days trying to fix this, searched google for hours, I may have seen the right answer but can't seem to make it work. I assume I need some kind of while True statement, or if;then, but as many times as i have tried, I'm pulling my hair out at this point. The code to the entire program is below:
def main():
star = '*' * 70
print star
print ("Nick's Electric Bill Calculator")
print star
watts = input("Enter the watts of appliance, or total watts of appliances ")
hours = input("Enter the number of hours that appliance(s) run per day ")
cost = input("Enter the cost in cents per KwH you pay for electricty " )
# print ("Don't be silly, there isn't more than 24 hours in a day!")
x = (watts * hours / 1000.0 * 30) * cost
total = x
print star
print ("""If you use %s watts of electricity for %s hours per day, at a cost of
%s cents per Kilo-watt hour, you will add $%s to your monthly
electric bill""") % (watts, hours, cost, total)
print star
playagain = 'yes'
while playagain == 'yes':
main()
print('Would you like to do another Calculation? (yes or no)')
playagain = raw_input()
I'm new to programming, I've only been learning Python for a few weeks, many thanks in advance for any advice.
An optimized version of #JamesRusso code :
def main():
star = '*' * 70
print star
print ("Nick's Electric Bill Calculator")
print star
watts = int(input("Enter the watts of appliance, or total watts of appliances"))
hours = int(input("Enter the number of hours that appliance(s) run per day"))
# Check that the hours number is good before getting to the cost
while (hours > 24) or (hours < 0):
print("Don't be silly, theres not more than 24 or less than 0 hours in a day ")
hours = int(input("Enter the number of hours that appliance(s) run per day "))
cost = int(input("Enter the cost in cents per KwH you pay for electricty "))
# We don't need an auxiliary variable x here
total = (watts * hours / 1000.0 * 30) * cost
print star
print ("""If you use %s watts of electricity for %s hours per day, at a cost of %s cents per Kilo-watt hour, you will add $%s to your monthly electric bill""") % (watts, hours, cost, total)
print star
if __name__ == '__main__':
playagain = 'yes'
while playagain == 'yes':
main()
print 'Would you like to do another Calculation? (yes or no)'
playagain = raw_input()
# Checking that the user's input is whether yes or no
while playagain not in ['yes', 'no']:
print "It's a yes/no question god damn it"
print 'Would you like to do another Calculation? (yes or no)'
playagain = raw_input()
I put your error message in an if statment, and the calculation code in an else. This way it won't do the calculation when the hour isn't correct and instead will exit main and go back to the while loop and ask the user if they will like to play again. Also as other user's have pointed out following what I did below you should add more error testing and messages for negative numbers, etc.
def main():
star = '*' * 70
print star
print ("Nick's Electric Bill Calculator")
print star
watts = input("Enter the watts of appliance, or total watts of appliances ")
hours = input("Enter the number of hours that appliance(s) run per day ")
cost = input("Enter the cost in cents per KwH you pay for electricty " )
if hours > 24:
print("Don't be silly, theres not more than 24 hours in a day ")
else:
x = (watts * hours / 1000.0 * 30) * cost
total = x
print star
print ("""If you use %s watts of electricity for %s hours per day, at a cost of %s cents per Kilo-watt hour, you will add $%s to your monthly electric bill""") % (watts, hours, cost, total)
print star
playagain = 'yes'
while playagain == 'yes':
main()
print('Would you like to do another Calculation? (yes or no)')
playagain = raw_input()
My python skills are a little rusty, but when I have to do stuff like checking input, I usually use a structure something like this:
hours = 0
while True:
hours = input("How many hours per day? ")
#first make sure they entered an integer
try:
tmp = int(hours) #this operaion throws a ValueError if a non-integer was entered
except ValueError:
print("Please enter an integer")
continue
#2 checks to make sure the integer is in the right range
if hours > 24:
print("Don't be silly, theres not more than 24 hours in a day ")
continue
if hours < 1:
print("Enter a positive integer")
continue
#everything is good, bail out of the loop
break
Basically, it starts by going into an 'infinite' loop. It gets the input, goes through all the checks to see if it is valid, and hits the break (leaving the loop) if everything went okay. If the data was bad in any way, it informs the user and restarts the loop with the continue. hours = 0 is declared outside the loop so it is still accessible in the scope outside, so it can be used elsewhere.
Edit: adding an idea to the example code that I thought of after seeing #Ohad Eytan's answer
The input you get from the user is a string type, but you compare it to int type. That's an error. You should cast the string to int first:
hours = int(input("How many hours per day? "))
# ----^---
Then you can do something like:
while hours > 24:
print("Don't be silly, theres not more than 24 hours in a day ")
hours = int(input("How many hours per day? "))
If you don't sure the user will input a number you should use a try/catch statemant.
Except from this you should validate you indent the code correctly

global name 'getYearlyCost2' is not defined

I'm using python for the very first time and I am stuck on this stinking problem and cant for the life of me figure out why its not working. When I try and run my program I can get an answer for the yearly cost without the modification (even though its wrong and I dont know why) but not the yearly cost with the modification.
I've tried rewriting it in case I missed a colon/parenthesis/ect but that didnt work, I tried renaming it. And I tried taking it completely out (this is the only way I could get rid of that annoying error message)
payoff file
from mpg import *
def main():
driven,costg,costm,mpgbm,mpgam = getInfo(1,2,3,4,5)
print("The number of miles driven in a year is",driven)
print("The cost of gas is",costg)
print("The cost of the modification is",costm)
print("The MPG of the car before the modification is",mpgbm)
print("The MPG of the car afrer the modification is",mpgam)
costWithout = getYearlyCost(1,2)
print("Yearly cost without the modification:", costWithout)
costWith = getYearlyCost2()
print("Yearly cost with the modification:", costWith)
While I know there is an error (most likely a lot of errors) in this I cant see it. Could someone please point it out to me and help me fix it?
Also I added my mpg.py in case the error is in there and not the payoff file.
def getInfo(driven,costg,costm,mpgbm,mpgam):
driven = eval(input("enter number of miles driven per year: "))
costg = eval(input("enter cost of a gallon of gas: "))
costm = eval(input("enter the cost of modification: "))
mpgbm = eval(input("eneter MPG of the car before the modification: "))
mpgam = eval(input("enter MPG of the car after the modification: "))
return driven,costg,costm,mpgbm,mpgam
def getYearlyCost(driven,costg):
getYearlyCost = (driven / costg*12)
def getYealyCost2(driven,costm):
getYearlyCost2 = (driven / costm*12)
return getYearlyCost,getYearlyCost2
def gallons(x,y,z,x2,y2,z2):
x = (driven/mpgbm) # x= how many gallons are used in a year
y = costg
z = (x*y) # z = how much money is spent on gas in year
print("money spent on gas in year ",z)
x2 = (driven/mpgam) # x2 = how much money is spent with mod.
z2 = (x2*y)
y2 = (costm + z2)
1,1 Top
Here's your immediate problem:
costWith = getYearlyCost2()
The function you're trying to call is named getYealyCost2() (no "r").
There are other problems that you'll find as soon as you fix that, such as no return statement in getYearlyCost() and trying to return the function getYearlyCost() in getYearlyCost2() and calling getYearlyCost2() without any arguments.
On top of that, import * is frowned upon, and then there's the use of eval()... but that'll do for starters.

Categories