简体   繁体   中英

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM