title: function description: A complete guide to Python functions: from basics to practice

#Python functions

1. Function basics: definition and abstraction

A function is not a mysterious concept - it is just a block of code that is encapsulated, can be called repeatedly, and is used to solve a single problem. From the perspective of programmers' daily development, the core value of functions lies in abstraction: you don't need to write a "add from 1 to 100" loop every time, just call it directlysum();There is no need to implement trigonometric functions from scratch every time, just usemath.sin()Just fine.

1.1 Standard definition syntax

Python usesdefkeywords to define functions. In industrial-grade code, Docstring and Type Hints are usually added - the former tells the caller what this function does, and the latter allows editors and static checking tools to know "what is passed in and what is returned", greatly improving the maintainability of the code.

import math

def area_of_circle(radius: float) -> float:
    """计算给定半径的圆的面积。
    
    参数:
        radius: 圆的半径,必须是正数
        
    返回:
        计算出的圆的面积,保留无限精度的float
    """
    return math.pi * radius ** 2

1.2 Details of return value

How the result is given inside the function directly affects how the caller uses it:

  • Single return: Use directlyreturnJust follow the content to be returned.
  • Multiple return values: Writereturn x, yThat's enough, Python will automatically package them into a tuple, which can be received with multiple variables when called, or indexed to obtain values.
  • Placeholder and empty return: If the function body has not figured out the logic yet, you can usepassPlaceholder; if not explicitly writtenreturn, or write directlyreturnIf nothing follows, Python will return by defaultNone

2. Function call: make the code block "move"

The defined function is just a "static template" in memory and must be called to be actually executed.

2.1 Three basic calling methods

# 方式1:直接传入字面量
print(area_of_circle(5.0)) 

# 方式2:传入变量,可读性更高
r = 10.5
s = area_of_circle(r)
print(f"半径为{r}的面积是: {s:.2f}")

# 方式3:把调用直接嵌在表达式中
total_area = area_of_circle(2) + area_of_circle(3)

2.2 Important mechanism of parameter passing

Understanding how Python passes values ​​to functions is more useful than simply remembering parameter names:

  1. Two calling methods:
  • Position call:f(a, b), the values ​​are passed in exactly in the order of parameters when the function is defined.
  • Keyword call:area_of_circle(radius=5.0), more clear, and can be passed out of order when there are many parameters.
  1. **What is going on at the bottom? ** Python uses object reference passing, not pure "value passing", nor pure "address passing":
  • If an immutable object (number, string, tuple, etc.) is passed in, reassigning or modifying the parameter inside the function will only create a new object and will not affect the external original variables.
  • If mutable objects (lists, dictionaries, collections, etc.) are passed in, the parameters will be modified in place** inside the function (such as.append().update()etc.) will directly and synchronously affect external variables, which requires special attention.

2.3 Dynamic call: parameter unpacking

If you already have a list, tuple or dictionary to store parameters, you don’t need to manually separate them one by one. Use*and**You can quickly unpack:

# 将列表/元组解包为位置参数
params = [5.0]
print(area_of_circle(*params))

# 将字典解包为关键字参数
def greet(name, age):
    print(f"你好,我叫{name},今年{age}岁")
user_info = {"name": "Alice", "age": 25}
greet(**user_info)

3. Deeply understand the parameter system: rules bring freedom

Python's parameter system is very flexible, but the order of definition must be strictly adhered to, otherwise an error will be reported directly. The following is organized into a table according to priority:

Parameter typesExample syntaxCore features
Positional parametersdef f(a, b)must be provided when calling and passed in strictly in order.
Default Parametersdef f(a, b=2)The default value must point to an immutable object (such asNone, integer, string) to avoid the trap of "default value reuse".
Variable parametersdef f(*args)Receive any number of positional parameters and automatically pack them into tuples.
Named keyword parametersdef f(*, city)use*,Cut off positional parameters and use them when calling forcefullycity='北京'This key-value pair format can effectively avoid confusion.
Keyword parametersdef f(**kw)Receive any number of keyword parameters and automatically package them into a dictionary, often used for extended functions or transfer parameters.

4. Recursive function: simplify the logic, but be sure to pay attention to the boundaries

Recursion means that the function calls itself. The core idea is to decompose a complex problem into sub-problems with "the same structure but smaller scale".

4.1 Classic entry case: factorial

def factorial(n):
    # 终止条件!没有它,函数会一直调用自己直到系统栈溢出
    if n == 1:
        return 1
    # 自调用,每次n减1,不断向终止条件靠近
    return n * factorial(n - 1)

4.2 Three Golden Rules of Recursion

  1. There must be clear termination conditions: For example, the aboven == 1, otherwise Python defaults to a recursion depth limit of about 1000 levels (can be passedsys.getrecursionlimit()view) will be triggered.
  2. Every recursion must be closer to the termination condition: For example, every timenSubtracting 1, you cannot calculate further away from the end value.
  3. Reasonably weigh performance: Recursive code is usually concise, but each call will consume function call stack space. In performance-sensitive scenarios (such as calculating very large Fibonacci numbers), it is recommended to use iteration (looping) instead of recursion.

4.3 Modern Python Optimization: Memoized Cache

Many recursions involve repeatedly calculating the same subproblem (such as finding Fibonacci numbers). Python 3.9+ provides a minimalist solution - just add a decorator!

from functools import cache  # 3.9+ 专用,比旧版 lru_cache() 更简洁

@cache  # 自动把计算过的 (n, 结果) 缓存起来,下次直接取用
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 测试:不加缓存计算 fib(40) 会明显卡顿,加上后瞬间出结果
print(fibonacci(40))

5. Industrial best practices and specifications

To write a function, not only must it run correctly, but it must also be easy to read, modify, and reuse:

  1. Single Responsibility Principle: A function only does one thing. For example, you cannot "calculate area", "print results", and "save to file" at the same time.
  2. Naming convention: all lowercase and underlined, starting with a verb (such ascalculate_taxvalidate_input)。
  3. Parameter verification: Use at the beginning of the functionisinstance()Check the type, use conditional statements to check the value range, and if it is unreasonable, immediately throw a clear exception (such asTypeErrorValueError)。
  4. Try to avoid side effects: Do not modify global variables at will inside the function, and do not directly modify the passed variable object in place - if you really need to change it, either write it clearly in the document, or return a new modified object.

6. Comprehensive practice: quadratic equation solver

Integrate the knowledge points learned previously and write a tool function that conforms to the specification:

import math
from typing import Tuple, Union

def solve_quadratic(
    a: Union[int, float],
    b: Union[int, float],
    c: Union[int, float]
) -> Tuple[float, float]:
    """求解标准形式的一元二次方程(仅实数解)。
    
    参数:
        a: 二次项系数,不能为0
        b: 一次项系数
        c: 常数项
        
    返回:
        两个实数解组成的元组,按从小到大排序
    """
    # 参数验证:检查类型
    if not all(isinstance(x, (int, float)) for x in [a, b, c]):
        raise TypeError("所有参数必须是整数或浮点数")
    # 参数验证:检查二次项系数
    if a == 0:
        raise ValueError("二次项系数 a 不能为0,否则不是一元二次方程")
    # 计算判别式
    discriminant = b**2 - 4*a*c
    # 参数验证:检查是否有实数解
    if discriminant < 0:
        raise ValueError("方程没有实数解")
    # 计算根
    sqrt_d = math.sqrt(discriminant)
    root1 = (-b + sqrt_d) / (2*a)
    root2 = (-b - sqrt_d) / (2*a)
    # 按从小到大排序返回
    return (root2, root1) if root2 < root1 else (root1, root2)

# 调用测试
try:
    print(f"方程 2x² + 3x + 1 = 0 的解为: {solve_quadratic(2, 3, 1)}")
except Exception as e:
    print(f"出错了: {e}")

7. Summary

Functions are the core cornerstone of Python programming: basic definitions and calls prevent code from being repeated, the flexible parameter system can adapt to various scenarios, recursion can simplify complex logic but boundary conditions must be set well, and memory caching can greatly improve efficiency in repeated calculation scenarios. Finally, remember to follow best practices - so your code can evolve from "just running" to "usable".