Reputation: 117
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!
Upvotes: 0
Views: 7325
Reputation: 365617
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.
Upvotes: 1