Python Forum
trouble with functions "def", calling/defining them
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
trouble with functions "def", calling/defining them
#11
There are a couple of errors here. First we still have the missing arguments problem. Function calcIncome takes three arguments: aTickets, bTickets and cTickets. When you call calcIncome(aRevenue) there is only 1 value for 3 positional arguments. We will fix this problem first.

One way to fix the problem and make this function more useful is get rid of the positional arguments. This is the same function, but it uses named arguments.
A_COST = 10
B_COST = 7.50
C_COST = 2.25

def calcIncome(aTickets=0, bTickets=0, cTickets=0):
    # revenue made from each and returns total revenue from sales
    return aTickets * A_COST + bTickets * B_COST + cTickets * C_COST

print('A Ticket Income', calcIncome(aTickets = 5))
print('B Ticket Income', calcIncome(bTickets = 5))
print('C Ticket Income', calcIncome(cTickets = 5))
Output:
A Ticket Income 50.0 B Ticket Income 37.5 C Ticket Income 11.25
A named argument has a default value. If I call calcIncome(5), the value 5 is used for the aTickets argument leaving no values for the b and c tickets arguments. However the function declaration says it is ok to not provide values for every argument and the default value will be used when no value is provided. Calling calcIncome(5) is the same as calling calcIncome(5, 0, 0)

There is a reason these are called "named arguments", and that is because we can use the argument name to specify which argument gets the value. If I wanted individual tallies for a, b and c tickets I was forced to do this when calcIncome used position arguments
print('A Ticket Income', calcIncome(5, 0, 0))
print('B Ticket Income', calcIncome(0, 5, 0))
print('C Ticket Income', calcIncome(0, 0, 5))
This works ok, but it is not as clear as the code above that uses a named argument. When I call calcIncome(aTickets=5) it is immediately clear to the reader that the number of aTickets is 5. The reader does not have to search for the function and look at the order of arguments,

That fixes the position argument problem and makes your function more useful. Now time to fix the "aRevenue not defined" problem.

"Where oh where is aRevenue defined? Oh where oh where can that be?" That is what the message says. Python is looking for something named "aRevenue" and it cannot find it. First Python looks in the function where aRevenu is used.
def showIncome(num_aTickets, num_bTickets, num_cTickets, aRevenue, bRevenue, cRevenue):
    income = calcIncome(num_aTickets, num_bTickets, num_cTickets)
    print('the revenue collected from total ticket sales is', income)
    print('the revenue collected from class a ticket sales is', aRevenue)
    print('the revenue collected from class b ticket sales is', bRevenue)
    print('the revenue collected from class c ticket sales is', cRevenue
In Python, variables are defined when you set their value. Is there anywhere in this function where you see "aRevenue ="? You don't see it, I don't see it, and Python doesn't see it.

But Python doesn't just give up. Next it looks for "aRevenue" in the module. A module in Python is just a file, so Python looks to see if "aRevenue" is defined in the file. You may look at the file and see "aRevenue" appears in the function calcIncome().
def calcIncome(aTickets, bTickets, cTickets):
      # revenue made from each and returns total revenue from sales
    aCost = 20
    bCost = 15
    cCost = 10
    aRevenue = aTickets * aCost
    bRevenue = bTickets * bCost
    cRevenue = cTickets * cCost
    return (aRevenue + bRevenue + cRevenue)
While it is true that the name "aRevenue" is used for a variable in calcIncome(), that variable is local to calcIncome() and cannot be used outside the function calcIncome(). There are many reasons for this, but the most important is that if Python did not work this way every variable used in every function would have to be unique. Not only that, but every function name would have to be unique. Any time you wrote any Python code you would have to search through every bit of code in your Python distribution to verify that any variable or function name you wanted to use had never been used before.

To make it possible to write Python code and to allow for collaboration, Python breaks up all of Python into things called "name spaces". Every file of Python code defines its own namespace. If I write a function and you write a program that uses my function you don't have to worry about what variable names I used. These namespaces are why you have to write things like:
import math
sqrt2 = math.sqrt(2)
The math module defines a namespace named "math". The "math" namespace contains a function named "sqrt". If I want to use the function I specify the namespace so Python knows where to look for the function.

Modules aren't the only namespace. In Python each function get's its own namespace. This lets you reuse variable names in functions that reside in the same module. Some Python modules are pretty big and I don't want to read all the code to see if I can use a variable named "i" in the function I am adding to the module. This function namespace is why "showIncome()" cannot see "aRevenue" inside the "calcIncome()" function. "aRevenue" is inside the "calcIncome()" namespace.

You might be tempted to get the variable using the namespace.attribute notation; calcIncome.aRevenue. This does not work. The reason this does not work is because the function namespace calcIncome() only exists while the code inside calcIncome() is executing. As soon as the function completes the variables local to the function are deleted and their memory reclaimed.

Knowing all about namespaces and named arguments it is clear how you should write this program.
A_COST = 10  ## These were not defined either
B_COST = 7.50
C_COST = 2.25

def calcIncome(aTickets=0, bTickets=0, cTickets=0):
    # revenue made from each and returns total revenue from sales
    return aTickets * A_COST + bTickets * B_COST + cTickets * C_COST 
 
def showIncome(aTickets, bTickets, cTickets):
    income = calcIncome(aTickets, bTickets, cTickets)
    print('Total ticket sales is', income)
    print('Class a ticket sales is', calcIncome(aTickets=aTickets))
    print('Class b ticket sales is', calcIncome(bTickets=bTickets))
    print('Class c ticket sales is', calcIncome(cTickets=cTickets))

showIncome(10, 10, 10)
Output:
Total ticket sales is 197.5 Class a ticket sales is 100.0 Class b ticket sales is 75.0 Class c ticket sales is 22.5
There are a few tricky things going on here like: calcIncome(aTickets=aTickets). This is less confusing if written as calcIncome(arg=value), but the two are very similar. In "calcIncome(aTickets=...)", the "aTickets is a named argument of the function "calcIncome()". The "aTickets" in calcIncome(...=aTickets) is the value of the "aTickets" argument of the "showIncome()" function. The code above is identical to this code that uses different names for the showIncome() function arguments.
def showIncome(a, b, c):
    income = calcIncome(a, b, c)
    print('Total ticket sales is', income)
    print('Class a ticket sales is', calcIncome(aTickets=a))
    print('Class b ticket sales is', calcIncome(bTickets=b))
    print('Class c ticket sales is', calcIncome(cTickets=c))
Reply
#12
you make valid points, and the reason it is setup in this way (could be written wrong) but that is how my teacher wants it written (she hasn't been much help at all)..
per my teacher:
Pg. 281 #7 Stadium Seating - your program MUST contain a main function, a calcIncome function, and a showIncome function.

Your main function should get the number of seats sold for each category. The values should be sent to a calcIncome function.
The calcIncome function should calculate the income from each category. Those values should be returned to the main function and those values should be sent to the showIncome function.
The showIncome function should calculate the total income generated from the ticket sales, display the income generated from each category AND display the total income generated.

(maybe this will help better understand my issue? maybe im overthinking it all or simply not grasping it fully)
Reply
#13
(Oct-21-2020, 03:38 AM)deanhystad Wrote: There are a couple of errors here. First we still have the missing arguments problem. Function calcIncome takes three arguments: aTickets, bTickets and cTickets. When you call calcIncome(aRevenue) there is only 1 value for 3 positional arguments. We will fix this problem first.

This clarifies a lot and helps me to understand it more (the explanations have been very helpful in this aspect)
also seeing the differences in how it is written from my view point to a more correct view point also helps greatly
Reply
#14
side note: I don't think anything was missing initially (looking back at the beginning when i posted this), just probably badly written
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Calling functions by making part of their name with variable crouzilles 4 749 Nov-02-2023, 12:25 PM
Last Post: noisefloor
  Calling functions from within a class: PYQT6 Anon_Brown 4 3,644 Dec-09-2021, 12:40 PM
Last Post: deanhystad
  Defining Functions theturtleking 4 2,733 Dec-07-2021, 06:45 PM
Last Post: deanhystad
  Defining multiple functions in the same def process sparkt 5 2,755 Aug-09-2020, 06:19 PM
Last Post: sparkt
  Calling C functions with PyObjects jibarra 6 2,656 Jul-17-2019, 02:52 PM
Last Post: jibarra
  Defining functions TommyAutomagically 1 1,842 Apr-25-2019, 06:33 PM
Last Post: Yoriz
  calling os functions not in module os Skaperen 2 2,588 Nov-10-2018, 01:54 AM
Last Post: Skaperen
  Trouble calling functions in main function RedSkeleton007 6 4,992 Nov-11-2017, 01:22 PM
Last Post: sparkz_alot
  Calling functions from another file jp2017 11 30,404 Oct-11-2017, 10:58 PM
Last Post: snippsat
  Having trouble defining variable tannishpage 6 5,564 Mar-23-2017, 01:04 PM
Last Post: Ofnuts

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020