Learn Python 3 The Hard Way, Ex. 21

I am working through the book and I am stuck on Ex. 21.

For Ex. 21, you define functions for addition, subtraction, multiplication, and division, and you pass arguments a and b to those functions. However, you do not explicitly assign anything to those variables. So, how do the defined functions know what is a and what is b? From the flow of the code, I can deduce what is “a” and what is “b”, but I would like to explicitly know. Does that make sense? How can you pass an argument as a variable to a function without defining that variable first?

To play with the code I added a variable c to the add function:

	def add(a,b,c):
		print(f”ADDING {a} - {b} - {c}")
		return a - b - c

The code runs until I hit:

	Traceback (most recent call last):
  File "2020-08-18, Ex21.py3", line 31, in <module>
    what = add(age, subtract(height, multiply(weight, divide(iq, 2))))
TypeError: add() missing 1 required positional argument: 'c'

Why can I not add as many numbers as I want?

The full code is below:

def add(a,b,c):
	print(f"ADDING {a} + {b} + {c}")
	return a + b + c
	
def subtract(a,b):
	print(f"SUBTRACTING {a} - {b}")
	return a - b
	
def multiply(a,b):
	print(f"MULTIPLYING {a} * {b}")
	return a * b
	
def divide(a,b):
	print(f"DIVIDING {a} / {b}")
	return a / b


print("Let's do some math with just functions!")

age = add(30, 5, 10)
height = subtract(78, 4)
weight = multiply(90, 2)
iq = divide(100, 2)

print(f"Age: {age}, Height: {height}, Weight: {weight}, IQ: {iq}")


#A puzzle for extra credit, type it in anyway
print("Here is the puzzle.")

what = add(age, subtract(height, multiply(weight, divide(iq, 2))))

print("That becomes: ", what, "Can you do it by hand?")

hello there,
the error is becaue of that you give three arguments to the addition function so you allways need to give it 3 arguments , but here:

what = add(age, subtract(height, multiply(weight, divide(iq, 2))))
you give it only 2 arguments i marked them with a bold and hash see them
what = add( #1age , #2 subtract(height, multiply(weight, divide(iq, 2))))

to correct that you need to give it a 3rd argument #3 example:
what = add( #1age , #2subtract(height, multiply(weight, divide(iq, 2))), (#3this is missed ))

hopefully i understand what you are trying to ask for in the first quation in you post , i think you are trying to figure out how defining function with an a, b any letter or a capple of letter a what we call in string

actually the letters you are putting in the parantheses are just as saying here we need to input something for the function to work with and give us input and you can put what ever you want inside the parantheses.

example :

#indentation does not show in here

def talking(a , b):
print (‘a is talking to b’)
talking(me ,you)

this will have an output of : me talking to you

because it use a and b means the first argument and the second argument nothing more
if i will writ it this way:

#indentation does not show in here

def talking(blabla, tomcruse):
print (‘blabla is talking to tomcruse’)
talking(me ,you)

this also will have an output of : me talking to you

so it is up to enter in the function when you want to run it .in this case me ,you i can put any thing i want in there to print them in the output

this because THE a AND b AND blabla AND tomcruse ARE NOT VARIABLES
THEY AR JUST TO SAY TO THE PYTHON HEY WE WANNA TO PUT AN ARGUMENT1 IN THE PLASE OF a AND ARGUMENT2 HERE IN THE PLACE OF b only

a variable is when we say for example a=4 that means for the computer tha store the vaue of 4 in a place in the memory and to not forget that place name it a so wenn ever i need that value(4) i will just aske you about the place a (variable a)

this is what i understand untill now from the book and it is working well for me i hope will work for you too

if you stil have doubts please ask more so i will give you the bestever of my understanding :slight_smile:

@bestever. Thank you. I would have never caught that, so thanks for the explanation. Very much appreciated. Rookie mistake, but…oh yeah, I’m a rookie, lol.

@bestever…based on your explanation, “a” and “b” are serving as place holders waiting for some input to replace those placeholders, correct?

So if we are on the same page: When we call add, we pass the values of 30, 5 to replace “a” and “b”. We then assign the result of 35 to age. That marries up with what the author explains in the video. I’m not sure why, but it clicks now. Thank you for your time! It is very much appreciated.

i think you get it right bro . and here is something maybe will make you undertand even better. a quiz

if i will define a function like this:

#inedentation is desmissed in the example

#there are 10 arguments (we can call them parameters also) or place holders as you said , in this function
def add(a, b, c, d ,g , what, ever, me, he ,she):
print (’ a + she’)

add(1, 3, 5, 7, 8, 5, 4, 2 ,8 ,9):

what is the out put of the function

notes: 1-you can put as many arguments or palce holders when defining a function
2-you can use some or all of them in the function to get the output
3-but you always need to put the number of the argument(aka place holders) in the function when using it (aka calling it running it) ex : in the above function every argument is holding a place and when we used them in the function we only used the first argument and the 10th (we can use the fourth and the sixth or any one we would like , we can use none of them but still we need to enter them when calling the function )

so what is the output of the function?

actually you would caught it without any one ,i was just a way that let you understand what u already was going to understand with this way or an other .
actualy think you for asking i really appreciate this interaction .
an additional info that you gonna caught sooner or latter or maybe right now

the memory is like a huge city that has all streets buildings look the same . the thing is we have nowhere to store our info other then in the memory in a computer and if we want to comback to the info to we store we can not serch for it by opening the memory and looking inside we will find just nothing also if we can it look all the same inside so that we set our info we need to restor to variables and when we need our info we just call variables.
actually i hear this from a teacher oneday and still have this idea on the variables in a programing language . if any one see this and find mistakes please give feadback it is much appriciated

1 Like

@bestever,

The answer is 10. 1+9.

right now you get the same understanding of this example as i do , just understand how the return works and go fowrard.
good luck :slight_smile:

@bestever. I appreciate the interaction as well. Thanks again for taking the time and providing good responses.

It might help to know how this is implemented, so here’s a detailed description of function calls.

If you define a function like this:

01: def add(a, b):
02:    return a + b
03: add(1, 2)

The 01: at the front is a line number, and it’ll be important later. It’s not actual python code, just pretending to be a text editor with your line number.

Now, when your script hits line 3 Python does something like this:

PUSH line:03
PUSH 1
PUSH 2
JUMP 01
add_result = POP

Internally python might technically do it differently but this is a really common pattern in all languages.

What PUSH does is prepare a value for the function call by pushing that value onto something called the stack. The stack is just a simple storage used to call functions and then clean up after. It’s a list that things go on from the end, and then pop off when you want to clean up.

Now the JUMP operation just jumps to the line of code where add() lives at line 1. Inside the add function you would have something like this:

b = POP
a = POP
ret = POP # that's the return location
result = ADD a, b
PUSH result
JUMP ret

Again, this is sort of fake “assembler” but the idea is, add pops those values 1,2 off the stack and assigns them to a and b variables. Then it uses the ADD instruction to add the two numbers, and assign them to result. You don’t really see result because Python is using temporary variables and things so you don’t have to think about this.

Once add() is complete it returns to the ret location that it got from that ret = POP line. That’s how it knows where to go back after a function call, and we just JUMP there going back to line 3. Also, remember that POP takes things off the stack so you don’t have functions polluting each other as you call them. The stack is like a little scratch pad for functions.

Now, how does the result of this addition get back to the calling site? Remember inside add we have this:

PUSH result

That means right before RETURN we pushed the value of result onto the stack, then jumped back and now it’s ready to be used at line 3 of the code where we do:

add_result = POP

So, if I were to turn this into a whole file with the fake assembler on the left, and the python on the right, it’d look like this:

01: b = POP               # def add(a,b)
  : a = POP
  : ret = POP # line:3
02: result = ADD a, b     #  return a+b
  : PUSH result
  : JUMP ret # line:3
  : 
03: PUSH line:03          # add(1, 2)
  : PUSH 1
  : PUSH 2
  : JUMP line:01
  : add_result = POP

You do NOT have to know assembler at all, but some people find it helps them understand the python if they know this simple detailed assembler too. Notice also that it’s only using a few commands: PUSH, POP, JUMP, ADD. You can do quite a lot of computation with those, and once you add TEST and JUMP_IF to check for true/false comparisons you’ve got yourself a computer.

Good morning Mr. Shaw, and thanks.

This does clear it up A LOT. I appreciate the detailed explanation.