Arguments and Returns

参数与返回值

#01 What this concept is really about

Arguments and returns are the two-way street of a function. Arguments are the values you hand in when you call a function, and returns are the values you hand back out when the function finishes. A function that takes clear arguments and gives back a clear result behaves like a small machine: you feed it ingredients, it does one job, and it produces an output you can use elsewhere. That simple picture is the heart of this topic.

When people say a function has clean inputs and outputs, they mean the function does not secretly depend on outside variables and does not quietly change things elsewhere in your program. Everything it needs arrives through its parameters, and everything it produces leaves through its return value. This makes the function predictable. You can read its name, look at its parameters, and understand what goes in. You can look at what it returns and understand what comes out.

This concept is really about communication and boundaries. A function is a small contract: give me these inputs, and I will give you this output. Once you start thinking in terms of that contract, your code becomes easier to test, easier to reuse, and easier to explain to someone else. Arguments and returns are not just syntax; they are the way you design the shape of your program.

#02 Why it matters in Python

Python makes functions easy to write, which is exactly why it is easy to write messy ones. Because Python does not force you to declare types or restrict how you pass data, a function can quietly reach out and read a global variable, or modify a list that belongs somewhere else. That freedom is powerful, but it also means the responsibility for clean design sits with you. Arguments and returns are how you take that responsibility seriously.

When a function receives what it needs as arguments and returns what it produces, you can move it, reuse it, and test it without dragging half your program along. You can call it from a script, from a test, or from another function, and it behaves the same way every time. This is especially valuable in Python because the language encourages quick experimentation. A clean function lets you experiment quickly without creating hidden side effects that surprise you later.

Returns also matter because they let you compose small pieces into larger ones. Instead of one giant block of code that does everything, you build small functions that each return a useful value, then feed those values into the next function. This style of programming is sometimes called pipelining or composition, and it is one of the most readable ways to structure Python code. Clean inputs and outputs are what make that composition possible.

#03 The mistake beginners often make

The most common mistake is reaching for global variables instead of passing arguments. A beginner writes a function that reads a variable defined at the top of the file, changes it, and returns nothing. The function appears to work, but its behavior depends on something outside itself. If you move the function, rename the variable, or call it in a different order, it breaks in confusing ways. This is the classic global-everything pattern, and it is worth avoiding early.

A related mistake is using a function only for its side effects. The function prints something, updates a list, or writes to a file, but it does not return a value. That is fine when the side effect is the whole point, such as printing a message. But when a function is doing a calculation, beginners often still print the result instead of returning it. Then the caller cannot use the result in another calculation, and the logic gets tangled with display concerns.

Another frequent issue is passing too many arguments, or passing vague ones. A function with six parameters named a, b, c, d, e, and f is hard to read and easy to call incorrectly. Beginners also sometimes mutate the arguments they receive, changing a list in place and returning nothing, which surprises anyone who expected the original list to stay the same. Each of these habits grows from the same root: not treating the function as a clear contract with defined inputs and outputs.

#04 A simple way to learn it

Pick one small task you already understand, such as calculating the total price of a few items, and write it as a function with a clear name. Give the function parameters for everything it needs, and make it return the result instead of printing it. Then call the function, store the returned value in a variable, and print that variable outside the function. This separates calculation from display, which is a habit worth building.

Next, deliberately break the global habit. If your first version reads a variable from outside, rewrite it so that value arrives as an argument. If it changes something outside, rewrite it so the change is returned and the caller decides what to do. Run the function twice with different arguments and confirm that the outputs differ in the way you expect. This repeatable loop, write, pass inputs, return output, call with new values, teaches the concept faster than reading about it.

Finally, add one test of your own. Call the function with a simple case and check the returned value against what you calculated by hand. Then call it with an edge case, such as an empty list or zero, and see whether the return still makes sense. You do not need a testing framework for this; a few print statements and a careful comparison are enough. The goal is to build the reflex of asking, what goes in, and what comes out, every time you write a function.

#05 What to pair it with

Arguments and returns pair naturally with scope. Scope is the rule that decides where a name is visible. When you pass values as arguments, you are deliberately bringing them into the function's local scope, and when you return a value, you are sending it back to the caller's scope. Understanding scope helps you see why a global variable feels convenient but creates hidden connections, while a parameter creates an explicit, visible one. The two ideas reinforce each other.

They also pair with readable code. A function with a descriptive name, a short list of well-named parameters, and a single clear return value reads almost like a sentence. Compare that with a function that takes no arguments, returns nothing, and depends on globals; the reader has to hunt through the file to understand it. Readability is not decoration here. It is the practical result of clean inputs and outputs, and it makes review, debugging, and collaboration much easier.

A third good pairing is small functions. When each function does one job, it usually needs only a few arguments and returns one obvious value. If you find a function with many parameters and several return paths, that is often a signal to split it. Pairing clean inputs and outputs with small, focused functions gives you a style that scales from tiny scripts to larger programs without becoming tangled.

#06 When to keep it simple

Not every function needs to return a value. Sometimes the purpose of a function is an action, such as printing a formatted message, writing a line to a file, or updating a display. In those cases, returning nothing is honest and clear. The key is to be intentional: if the function's job is a side effect, name it like an action, and do not pretend it is a calculation. Clean design is about matching the function's shape to its purpose.

It is also fine to use a module-level constant for values that truly never change, such as a fixed conversion factor or a default message. The problem is not globals in general; the problem is global mutable state that functions read and write invisibly. A constant that everyone reads and nobody changes is harmless and often clearer than passing the same value through many layers of functions. Keep the distinction in mind: constants are fine, shared mutable state is where trouble starts.

Finally, keep it simple when the program is genuinely small. A short script that reads a file, processes it, and prints a result does not need a carefully layered function design. You can start with straightforward code and refactor into functions with clean arguments and returns when the script grows or when you need to reuse a piece. Simplicity means choosing the smallest structure that keeps the code clear, not applying every technique everywhere.

#07 Questions beginners ask

Q: Should every function return something? A: No. Functions that perform an action, such as printing or saving, often return nothing, and that is fine. The important thing is to be clear about whether the function's purpose is to produce a value or to cause an effect. If it produces a value, return it; if it causes an effect, name it like an action and keep the effect obvious.

Q: Is it bad to use global variables at all? A: Not always. Constants that never change are usually fine, and small scripts can use module-level values without much trouble. The habit to avoid is functions that quietly read and modify shared global state, because that makes behavior hard to predict. Prefer passing values in as arguments and returning results out, and reserve globals for things that are genuinely constant.

Q: How many arguments is too many? A: There is no fixed number, but readability is the guide. If a call is hard to read or easy to mix up, the function probably needs fewer parameters or a clearer grouping. A short list of well-named arguments is easier to use correctly than a long list of vague ones. When in doubt, split the function or group related values into a single, clearly named structure.