Ben Wiese Ben Wiese - 2 months ago 6
Python Question

My variable is defined but python is saying it isn't?

I keep getting an error telling me that the name

hourly_pay
is not defined, but I have it defined inside the
main
function.

I'm a beginner as I've just started class but to me it looks like it should be working:

commission_pay_amount = .05
income_taxes = .25
Pay_per_hour = 7.50

def main():
display_message()

hourly_pay = float(input('Please enter amount of hours worked: '))

commission_pay = hourly_pay * commission_pay_amount
gross_pay = hourly_pay + commission_pay
witholding_amount = gross_pay * income_taxes
hourly_paying = Pay_per_hour * hourly_pay
net_pay = gross_pay - witholding_amount

display_results()

def display_message():
print('This program is used to calculate')
print('the hourly pay, commission amount,')
print('the gross pay, the withholding amount,')
print('and the net pay amount')
print()

def display_results():
print('The hourly pay is $', format(hourly_pay, ',.2f'))
print('The commission amount is $', format(commission_pay, ',.2f'))
print('The gross pay is $', format(gross_pay, ',.2f'))
print('The witholding amount is $', format(witholding_amount, ',.2f'))
print('The net pay is $', format(net_pay, ',.2f'))

main()

Answer

In python (in contrast to JavaScript), variables are locally scoped by default. This means that the variables are only accessible inside the function they are defined in. This behaviour can be overridden, but usually you do not want that.

To illustrate the difference, take a look at this python transcript:

>>> var1 = "this is global"
>>> def foo():
...   var1 = "this is local"
...   print(var1)
... 
>>> print(var1)
this is global
>>> foo()
this is local
>>> print(var1)
this is global

As you can see, even though var1 is assigned to in the foo() function, the value of the var1 name does not change in the global scope. If we had not defined var1 globally at all, the two print(var1) calls outside foo() would fail with a NameError, just like your code does.

The ultimate solution to your problem is to either handle output in the main() function, or pass the values to the display_results() function (the latter is generally preferred, keep logic and output separated):

def main():
    display_message()
    hourly_pay = float(input('Please enter amount of hours worked: '))
    commission_pay = hourly_pay * commission_pay_amount
    gross_pay = hourly_pay + commission_pay 
    witholding_amount = gross_pay * income_taxes  
    hourly_paying = Pay_per_hour * hourly_pay
    net_pay = gross_pay - witholding_amount

    display_results(hourly_pay, commission_pay, gross_pay, 
                    withholding_amount, net_pay)

def display_message():
    print('This program is used to calculate')
    print('the hourly pay, commission amount,')
    print('the gross pay, the withholding amount,')
    print('and the net pay amount')
    print()

def display_results(hourly_pay, commission_pay, gross_pay, 
                    withholding_amount, net_pay):
    print('The hourly pay is $', format(hourly_paying, ',.2f'))
    print('The commission amount is $', format(commission_pay, ',.2f'))
    print('The gross pay is $', format(gross_pay, ',.2f'))
    print('The witholding amount is $', format(witholding_amount, ',.2f'))
    print('The net pay is $', format(net_pay, ',.2f'))

The official Python tutorial also has a few words on function scopes (emphasis mine):

More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables cannot be directly assigned a value within a function (unless named in a global statement), although they may be referenced.