3

I'm trying to learn Python and I'm really struggling with getting my code into self-contained functions. Here is an example:

def get_inputs():
    sales_amount = float(input("Enter total sales amount: "))

def calculate_discount(sales_amount):
    discount_amount = sales_amount * 2 
    return discount_amount

def output():
    print ( discount_amount )

def main():
    get_inputs()
    calculate_discount(sales_amount)
    output()

main()

Running this returns

File "/Users/Desktop/assA3.py", line 17, in <module>
main()

File "/Users/Desktop/assA3.py", line 14, in main
calculate_discount(sales_amount)

NameError: name 'sales_amount' is not defined

I thought the variable sales_amount was defined by the user input before it is referenced later. I can't figure out what I'm missing.

I apologise for how basic this problem is but I'm clearly misunderstanding something fundamental and I'm just really struggling. Any help would be greatly appreciated. Thanks.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
c3066521
  • 61
  • 1
  • 1
  • 7

4 Answers4

4

You are trying to use function scope variables in other functions. Nothing outside of function get_inputs can see variable sales_amount, its a variable local to that function. You will encounter the same issue with discount_amount, which is scoped to calculate_discount.

Instead return the values and pass them to other functions.

def get_inputs():
    return float(input("Enter total sales amount: "))

def calculate_discount(sales_amount):
    discount_amount = sales_amount * 2 
    return discount_amount

def output(discount_amount):
    print ( discount_amount )

def main():
    inputs = get_inputs()
    discounts = calculate_discount(inputs)
    output(discounts)

main()

The dirty option is to make them globals

def get_inputs():
    global sales_amount
    sales_amount = float(input("Enter total sales amount: "))

def calculate_discount(sales_amount):
    global discount_amount
    discount_amount = sales_amount * 2 
    return discount_amount

def output():
    print ( discount_amount )

def main():
    get_inputs()
    calculate_discount(sales_amount)
    output()

main()

Globals are slower, make your code more difficult to maintain and are bad for a whole raft of reasons.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
  • Thankyou Paul and others below. Speedy and comprehensive, I really appreciate it. – c3066521 May 20 '15 at 22:55
  • Done and thanks again. Just a quick follow-up. Taking the first example of the get_inputs function, am I able to return two separate values? eg: return input1, input2 – c3066521 May 21 '15 at 12:53
1

The simple answer is to pass sales_amount out of gets_input():

def get_inputs():
    sales_amount = float(input("Enter total sales amount: "))
    return sales_amount

and to use it in main():

def main():
    sales_amount = get_inputs()
    calculate_discount(sales_amount)
    output()

If you want to make it "self-contained" then you want to use classes:

class Sales(object):
    def get_inputs(self):
        self.sales_amount = float(input("Enter total sales amount: "))

    def calculate_discount(self):
        self.discount_amount = self.sales_amount * 2 

    def output(self):
        print ( self.discount_amount )


def main():
    my_sale = Sales()
    my_sale.get_inputs()
    my_sale.calculate_discount()
    my_sale.output()

main()
Brent Washburne
  • 12,904
  • 4
  • 60
  • 82
0

in each of get_inputs, calculate_discounts and main, sales_amount is a local variable. It might make more sense to you if each subroutine used a different variable name where presently all three use sales_amount.

I suggest that get_inputs return a result, and that main store the result of get_inputs into a variable that is then passed to calculate_discounts.

Mike Crawford
  • 2,232
  • 2
  • 18
  • 28
0

This is because variables defined in functions are local in Python.

See this StackOverflow answer to help you understand from where you can access variables.

In your case, you should just pass sales_amount as a parameter to your function, as others have pointed out :)

Community
  • 1
  • 1
laugri
  • 597
  • 6
  • 13