As your control-flow code grows, functions let you split logic into named blocks, and modules let you separate files for reuse and testing. We'll move from basic function syntax to parameters, return values, and module imports step by step.
Key terms
- Parameter: The named placeholder in a function definition that receives input values.
- Module: A single Python file whose functions can be imported elsewhere.
- Type hint: A notation such as
name: strthat expresses the expected type for variables or function I/O. if __name__ == "__main__": A guard that runs code only when the file is executed directly, not when imported.
Core ideas
Study memo
- Time required: 60 minutes
- Prereqs: Basic conditionals/loops plus a uv-backed project
- Goal: Define functions and reorganize logic into modules for reuse
Functions give logic a name; modules divide functionality by file. Together they make repeated calculations reusable and easier to test.
Code examples
Function definition basics
def greet(name: str) -> str:
return f"Hello, {name}!"
message = greet("Jimin")
print(message)
Functions accept inputs via parameters and return values with return. Add type hints to clarify intent.
Default and keyword arguments
def notify(message: str, urgent: bool = False):
prefix = "[URGENT] " if urgent else "[INFO] "
print(prefix + message)
notify("Deployment complete")
notify("Error detected", urgent=True)
Defaults keep call sites short, and keyword arguments (urgent=True) increase readability.
Variadic arguments
def combine(*values: str, separator: str = ", ") -> str:
return separator.join(values)
result = combine("A", "B", "C", separator=" | ")
print(result)
*values captures any number of positional inputs as a tuple. Use **kwargs to capture key–value pairs as a dictionary when needed.
Split functions into modules
Project structure example:
python-playground/
├─ app.py
└─ helpers/
└─ reports.py
Define functions inside helpers/reports.py:
# helpers/reports.py
def summarize_scores(scores: list[int]) -> dict:
total = sum(scores)
average = total / len(scores)
return {"total": total, "average": round(average, 2)}
Import them in app.py:
from helpers.reports import summarize_scores
scores = [82, 75, 91]
report = summarize_scores(scores)
print(report)
Splitting modules makes testing and reuse easier. Any script can import the same helper without duplicating code.
🧱 What counts as a module? Every Python file is a module. Group related behavior in its own file, then import it wherever you need the functionality.
Practical example: layered report generator
# services/reports.py
def create_summary(records: list[dict]) -> dict:
total = len(records)
completed = sum(1 for record in records if record["done"])
return {"total": total, "completed": completed}
# cli/report_command.py
from services.reports import create_summary
def render_report(records: list[dict]) -> str:
summary = create_summary(records)
return f"{summary['total']} tasks total, {summary['completed']} completed"
Placing core logic in services and handling I/O in CLI modules keeps test scopes clean and splits team responsibilities (data processing vs. presentation).
Module responsibility map
Visualizing these paths helps you decide where new functionality belongs as the project grows.
if __name__ == "__main__":
Run code only when the module executes directly:
def main():
print("Running main logic")
if __name__ == "__main__":
main()
When another file imports this module, main() will not run automatically, preventing accidental side effects.
Why it matters
Functions make logic testable; modules make collaboration easier. Guarding entry points with if __name__ == "__main__" prevents accidental execution when importing the same file elsewhere.
Practice
- Follow along: Create
helpers/summarize_scores.py, reproduce the function, and import it fromapp.py. - Extend: Add a display function like
render_reportin a separate file and call it frommain(). - Debug: Intentionally misspell a module path to trigger
ModuleNotFoundError, then fix it with the correct relative path or an__init__.py. - Definition of done: At least two files import each other's functions, and the execution entry lives inside an
if __name__ == "__main__"block.
Wrap-up
Functions and modules let you organize code by responsibility, making testing and reuse straightforward. This structure shines once you start handling files, JSON, and external data—which is exactly what we'll cover next.
💬 댓글
이 글에 대한 의견을 남겨주세요