Functions
Why we need functions
Analogy
- You press a button on a coffee machine and coffee comes out.
- You do not know how many grams it ground, what temperature the water hit, or how long it brewed. You do not care. You gave it an input and it gave you a result.
- That is a function: a named box of work, with something going in and something coming out.
- The person using it needs to know what goes in and what comes out. Nothing else.
Say you calculate a discount in four different places. Without a function that logic is copied four times, and when the rule changes you have to find all four. Miss one and your app quietly charges the wrong price.
What is a function?
Definition
A function is a named piece of work you can run whenever you like.
Defining it teaches the computer a new word. Calling it actually runs the work. A definition is the recipe; a call is cooking.
Beginners often write a beautiful function, run the file, see no output and get confused. The function was never called.
Parameters and arguments
A function gets more useful when you can hand it something.
def greet(name): # name is a parameter print("Hello, " + name) greet("Amit") # "Amit" is an argumentThe two words trip people up, so here is the short version. Parameter is the placeholder in the definition, the empty slot. Argument is the real value you drop into it at the call.
You can have several, and order matters. introduce(22, "Sara") is nonsense, and the computer will not stop you.
return, and why it is not print
return hands a result back to whoever called the function. Two things about it that everybody hits.
One: return ends the function immediately. Anything written after it never runs.
Two: print and return are completely different.
def add_p(a, b): print(a + b) # shows it on screen, gives back nothing def add_r(a, b): return a + b # hands the value back to be used x = add_p(2, 3) # prints 5, but x is Noney = add_r(2, 3) # prints nothing, but y is 5Note
print talks to the human. return talks to the rest of your program. If you want to use the answer, you need return.
A function with no return still returns something: Python gives back None, and Java and C call this a void function.
What actually gets passed in
A subtle one, and worth understanding early because it causes real bugs.
With simple values, the function gets a copy. It scribbles on the copy and the original never moves.
With lists and objects, the function gets the address. There is no copy, so both names point at the same list and the change is visible outside.
def add_item(lst): lst.append(4) items = [1, 2, 3]add_item(items)print(items) # [1, 2, 3, 4]The one-line rule: numbers and strings are safe to pass around; lists and objects can be modified by the function you hand them to. The memory chapter shows why.
Variables inside a function stay inside
Every call creates a fresh, private workspace, built when the function starts and thrown away when it finishes.
This is a feature rather than a limitation. It means you can use the name i or count inside a function without ever worrying about what the rest of the program is doing with those names.
Recursion
A function is allowed to call itself. That sounds like a trick and it is genuinely useful.
def factorial(n): if n == 1: # base case, the stopping point return 1 return n * factorial(n - 1)Every recursive function needs two things: a base case where it stops calling itself, and a step that moves towards that base case.
Watch out
Miss either one and it calls itself forever. It will not run forever, though - it crashes with an error called stack overflow, and the memory chapter explains exactly why.
What makes a good function
- One job. If the name needs the word "and", it is doing two things
- A name that says what it does.
calculate_totalbeatsdoStuff - Small. If it does not fit on your screen, it probably wants splitting
- Few parameters. More than four usually means something needs rethinking
- Predictable. Same input, same output, no surprises
Mistakes to watch for
Watch out
- Defining a function and never calling it, then wondering why nothing happened.
- Using
printwhere you neededreturn. - Forgetting the brackets.
greetis the function itself,greet()runs it. - Writing code after
returnand expecting it to run. - Wrong argument order.
- Recursion with no base case.
- Assuming a function cannot change a list you passed in. It can.
Quick recap
- A function is named, reusable work: input in, output out
- Defining teaches it, calling runs it
- Parameters are the slots, arguments are the values
returnsends a value back and ends the function on the spotprintis for people,returnis for code- Variables inside a function are private to that call
- Simple values are copied, lists and objects are passed by address
- Recursion must have a base case
Key takeaway
A function takes something in, does one job, and hands something back. Print is for people, return is for code.