What a function is
A function means gathering a few lines of code in one place, giving them a name, and from then on calling that name instead of repeating the lines. Its real value is not saving typing; it is that every decision made inside it now lives in exactly one place.
- Lesson 7 of 14
- Beginner
- Free, no signup
The four pieces that make a function
-
Input
The thing that differed between the repeated copies. If nothing differs, no parameter is needed.
-
Logic
What the function does, which its name should say. If you have to say "and" to describe it, you have two functions.
-
Output
What is handed back with return. A function that only prints has no output and cannot be used in the next calculation.
-
Reuse
Every decision made inside the function now lives in one place and changes in one place.
The fourth piece is what separates a function from a few ordinary lines. Code needed once, in one place, does not have to become a function.
Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.
What exactly is a function, and how is it different from a few ordinary lines?
A function is a few lines of code with a name. Having a name is what makes the difference: code without one is just a spot in your file, while code with one can be called from anywhere in the program and you no longer need to know what goes on inside.
def display_name(user):
name = user["name"].strip()
if name == "":
return "guest"
return nameTwo separate things are happening here and beginners usually mix them up. The first line is the definition: it says such a thing exists and this is its job. It does not run, it is only registered. The call is somewhere else, when you write display_name(user_a), and only then do those five lines run.
So a function that is defined but never called anywhere does nothing at all and reports no error either. That is one of the most common reasons behind "my code does not run", especially when someone moves code inside a function and forgets to call it at the bottom of the file.
And the best definition of a function is not that it reduces repetition; it is that it gives a name to a thought. When you write display_name, the person reading your code no longer has to read four lines to understand what is happening. A good name removes four lines of explanation, and that is the largest thing a function gives you.
What is the difference between a parameter and an argument?
These two words look at one thing from two sides, which is exactly why they get mixed up. A parameter is the name you write when defining the function, the user on the first line of the example above. An argument is the real value you send when calling it, the user_a.
A parameter is a blank and an argument is what fills the blank. To be more precise: the parameter belongs to the definition and there is only one of it, while the argument belongs to each call and can differ every time. A function with one parameter may be called fifty times across a program with fifty different arguments.
Knowing this distinction is useful in practice rather than in vocabulary. When you see an error saying the function wanted two inputs and got one, it is talking about the number of arguments, not about the definition. Which means the definition is fine and the mistake is on the very line where you called it. That single diagnosis narrows the search from a whole file to one small line.
One habit that makes life easier: name your parameters so that they say what they expect. def send(to, subject, body) reads without any explanation, while def send(a, b, c) forces you back inside the function every time, which is precisely what the function was meant to save you from.
Parameter, argument, and what comes back
Definition: the parameter
written once
- A blank with a name
- Its name should say what it expects
Call: the argument
can differ every time
- The real value that fills the blank
- One function, fifty calls, fifty arguments
and one thing comes back
The return value
what return hands back, not what gets printed
- With no return, the function hands back nothing
- return ends the function on the spot
A function has one definition and any number of calls. An error saying the input count does not match is always about the call side, never the definition.
What does return mean, and why does print not replace it?
This is where the largest number of beginners get stuck, and the root of it is a simple misunderstanding: print shows something on the screen, while return hands a value back to whoever called the function. Those are not the same job at all.
def double(n):
print(n * 2)
result = double(5)
print(result)The screen shows 10 first and then None. The ten was printed by the function itself, but result is empty, because this function returned nothing. A function with no return hands back None in Python, and the equivalent in other languages.
def double(n):
return n * 2
result = double(5)
print(result)Now nothing is printed inside the function and result is ten, which is to say something you can use in the next calculation. The practical difference is this: a function that prints looks correct when you test it by hand, and breaks the moment you want to use its result. Which is also why this bug is usually found late.
One more point that gets said less often: return ends the function immediately. Any line written after it inside that same function does not run. This is not a restriction, it is a tool: in the first example on this page, return "guest" means the last line is never even evaluated. This is called an early return and it rescues code from nested conditions.
A real refactor: three repetitions, one function
Suppose you have written these same four lines in three places in a program, differing only by one variable:
name = user_a["name"].strip()
if name == "":
name = "guest"
print(name)
name = user_b["name"].strip()
if name == "":
name = "guest"
print(name)The right way to extract a function has three steps, and the second is the one usually skipped. First, find the repetition. Second, and more importantly, find what differs between the three copies; that thing is your parameter. Third, write a function that takes that difference as an input.
def display_name(user):
name = user["name"].strip()
if name == "":
return "guest"
return name
print(display_name(user_a))
print(display_name(user_b))What has actually been gained is not a few saved lines. It is that the word guest is now written in exactly one place. Tomorrow, when you decide to write something else instead, you change one line and you are done.
And what used to happen with the previous version? You would change two of the three places and not see the third. The program would raise no error either; one page of your site would simply show the old word for months and nobody would notice. Repeated code is dangerous for that reason, not because it is ugly.
Five steps to pull a function out of repeated code
-
1
Find the repetition
Twice can be coincidence, three times is not.
-
2
Find the differences
Everything that differs between the copies is a parameter.
-
3
Give it a name
If you cannot find a name, you do not yet know what this code does.
-
4
Write one function
The differences become inputs and the rest stays inside.
-
5
Replace all three places
Leave one behind and that is the one keeping the old behaviour for months.
The second step is the one that gets skipped and then the refactor breaks. Miss the differences between the copies and you build a function that quietly changes the behaviour of one of them.
Four lines of code that are called 181 times
The example above is made up. This one is not. The infographic library of this very site has a function whose job is one thing only: take a four language array, pull out the text for the page's language, and fall back to Persian if that language is missing.
function rgb_dg_t( $value, string $lang ): string {
if ( is_array( $value ) ) {
return (string) ( $value[ $lang ] ?? $value['fa'] ?? '' );
}
return (string) $value;
}On the day this lesson was checked, that function was called 181 times across the four files of the diagram library. Every title, every label, every note under every figure you see in this learning section passes through those four lines.
Now look at that ?? 'fa' in the middle of the third line. It is a decision: if the translation of a label has not been written yet, show the Persian text rather than an empty figure. That decision is written in one place and takes effect at 181 points. If we change our mind tomorrow and would rather show nothing than Persian, one word changes.
And the other side of the same coin, which should be said plainly: one mistake in those four lines also breaks 181 places at once. A function this central has to be read more carefully than the code calling it, for exactly that reason. Concentration buys you benefit and risk together, and they are made of the same material.
When not to write a function, and where we duplicated code on purpose
You hear the rule "never repeat yourself" a lot, and like every absolute rule it stops working somewhere. A function that forces you to scroll to the top of the file and back in order to understand four lines takes more time from you than it saves.
Three signs a function was not needed: it is called from one place and probably always will be; its name is effectively the code inside it, like a function named add_one that adds one; and writing it takes six parameters. The last is the most important: a large number of parameters usually means the function does more than one job. The simple test is to try saying what it does in one short phrase; if you had to say "and", you have two functions.
Now the opposite case, from this site. We have two separate plugins and both have to show a price in toman with a thousands separator and Persian digits. The code for that is nearly identical in both, yet they are two separate functions with two different names, one in the ranking plugin and one in the hosting plugin.
That duplication is not a mistake, it is a decision. Each plugin has to work on its own, even when the other one is switched off. If one used the other's function, deactivating a plugin would break pages belonging to the other. The price we pay for that independence is real and we do not hide it: any change to how a price is displayed has to be made in two places, and we have to remember that it is two. We say this so that you know there is not always a third way; sometimes you have to choose between two costs and then write that choice down somewhere so the next person does not think you forgot.
The fast path, with AI
Pulling a function out of repeated code is exactly what models do well, and exactly what quietly changes a program's behaviour when done carelessly. So the recipe below has one unusual clause that separates it from a plain refactor request: it asks the model to list, before anything else, every way the three copies differ. That list is the thing you did not see, and it is where the refactor breaks. This is judgment work, so it wants a frontier model rather than a fast one; our current pick among coding models sits in the AI section of this site.
- Copy all three repeated blocks in full, not one of them with a note saying "the others are similar". That word "similar" is exactly where the refactor breaks.
- Send the recipe below and read only the list of differences first, before looking at the proposed code. If that list contains something you did not know about, stop there and decide which behaviour is the correct one before anything else.
- Take the proposed function name seriously but do not accept it blindly. If explaining the name forces you to say "and", the function does two jobs and should become two.
- After the replacement, open all three places again and make sure none was left behind. Missing one of the three is the most common mistake in this work and it produces no error at all.
Copy-ready recipe
These three blocks of code are repeated in my program and I want to extract one function from them.
{first block}
{second block}
{third block}
Before anything else, and before writing any code, give me this:
1. A list of every difference between the three blocks, including small ones such as the order of two lines or an extra condition in one of them.
2. For each difference, say whose behaviour changes if we make them all identical.
After that:
3. Propose one function that takes the real differences as parameters, with a name that says what it does.
4. The three calls that replace the three blocks.
5. Say how the proposed function behaves on an empty or missing input.
If any of this needs code I have not given you, say which and why; do not guess.
Before you trust the output: The first clause is the value of the whole recipe, and removing it turns this into an ordinary refactor request that anybody writes. And the last sentence is not there by accident: if one of those three blocks calls a function whose code you did not send, the model guesses its behaviour from its name and writes that guess down in a definite tone. Until you have run all three places yourself after the replacement, the refactor is not finished.
AI in this kind of work
Writing functions is one of the jobs language models do flawlessly, because the shape is fixed and examples were plentiful in their training data. So what is left for you is judging the function's contract rather than writing it: what does it take, what does it hand back, what does it do on bad input, and does its name really say what it does. Our position is to keep the model in the role of critic rather than author for this topic: ask it to criticise the function it just wrote, in a separate message.
Tools that actually help
- Claude Code For this topic its best quality is that it sees the repository, so when you ask where a function is called from it goes and counts instead of guessing. Exactly the job we did in this lesson on that four line function. It installs free but does not run without a Claude subscription or an Anthropic Console account, and Iran is not on the supported-countries list.
- Claude Good for criticising a function's contract: ask whether it does more than one job and whether its name is accurate. Iran is on neither of Anthropic's two supported-countries lists; we read that on Anthropic's own page rather than measuring it.
- Gemini Its study mode, Guided Learning, asks questions instead of handing over answers, which suits settling the difference between return and print, the hardest part of this lesson, better than getting a direct answer does. Google's own page says the Gemini web app runs in over 230 countries and territories, and Iran is not on that list.
Where it backfires
The specific risk in this topic fits in one sentence: a model will happily build a function with six parameters that does three jobs, because you said "one function" and it delivered exactly one. The code works, it even tests fine, and six months later nobody dares touch it. So count the parameters yourself and ask every time whether this function can be described in one short phrase.
The second risk is more precise and particular to this work: when you ask a model to gather several similar blocks into one function, it flattens the small differences between them, deliberately or not, because you asked for them to be made one. The result is a quiet change in the behaviour of one of those blocks, with no error anywhere. Anthropic itself calls this class of unsupported confidence hallucination in its own documentation and explains how to reduce it. For how each of these tools can be paid for from Iran, see the buying guide, and for our current pick among coding models, the best AI for coding.
Sources: Anthropic: reduce hallucinations Anthropic: supported countries Claude Code: overview and install Google: where the Gemini web app is available
Where this advice stops
The examples on this page are Python and one of them PHP; the idea is the same in every language but the writing differs. We have also deliberately left out three subjects, because each wants a lesson of its own: variable scope and what is visible inside a function, default values and optional inputs, and the difference between a function and a method called on an object. And one question whose honest answer is that there is no rule: how many lines a function should be. Any number you are given came from nowhere; the real test is whether you can state its job in one short phrase, and that test has nothing to do with a line count.
From our own work
The number in this lesson is not a guess. On the day this page was checked we counted calls to rgb_dg_t across the four files of this site's own diagram library: 21 in diagram.php, 86 in diagram-lib.php, 62 in diagram-lib2.php and 12 in diagram-chart.php, for 181 calls to a function whose body is four lines. What that number shows, and what matters for this lesson, is not saved typing: the entire multilingual policy of this site's infographics is compressed into one expression inside that function, ?? $value['fa'], and that single expression decides what is displayed when a label's translation has not been written. Change that policy and one word changes with 181 points behind it; get it wrong and the same 181 points break together.
Real follow-up questions
What is the difference between a function and a method?
A method is a function attached to an object, usually working on that object's own data. In the examples on this page strip() is a method, because it is called on the string itself; display_name() is a standalone function. Until you move into object oriented programming, the difference is only in how they are written.
Why does my function return None?
Because there is no return in it, or because the return sits on a path this particular run did not take. The first usually means you used print where you meant return; the second means one branch of your conditions was left without a return. Both are diagnosed by looking at the last line of the function.
How do I know a piece of code should become a function?
Two signs are enough. First, that it has been repeated three times; twice can be coincidence, three times is not. Second, that you can say what it does in one short phrase; if you found that phrase you have also found the function's name, and if you did not, you do not yet know what the code does.