🐍 前端开发 0 基础学 Python 入门指南:函数篇

43 阅读16分钟

🐍 前端开发 0 基础学 Python 入门指南:函数篇

从 JavaScript 函数到 Python 函数,掌握参数、返回值和高级特性!

📝 一、什么是函数?

函数是组织好的、可重复使用的代码块,用于实现单一或相关功能。Python 的函数与 JavaScript 类似,但有更强大的参数处理能力。

1.1 基本语法

# 基本函数定义
def greet(name):
    return f"Hello, {name}!"

# 调用函数
result = greet("小明")
print(result)  # Hello, 小明!

核心特点:

  • 使用 def 关键字定义函数
  • 使用 return 返回值
  • 支持多种参数类型
  • 强大的参数默认值和解包功能

🆚 二、Python vs JavaScript:函数对比

2.1 基本语法对比

特性JavaScriptPython
定义关键字function=>def
参数类型注解TypeScript 支持原生支持
默认参数function(a = 1)def func(a=1):
不定长参数...args*args, **kwargs
匿名函数(x) => x * 2lambda x: x * 2
返回值return 或自动返回必须使用 return
文档字符串JSDoc 注释docstring(三引号字符串)
// JavaScript - 函数定义
function add(a, b) {
  return a + b
}

// 箭头函数
const multiply = (a, b) => a * b

// 默认参数
function greet(name = 'Guest') {
  return `Hello, ${name}!`
}
# Python - 函数定义
def add(a, b):
    return a + b

# 匿名函数(lambda)
multiply = lambda a, b: a * b

# 默认参数
def greet(name="Guest"):
    return f"Hello, {name}!"

💡 三、函数定义

3.1 基本定义

# 无参数函数
def say_hello():
    print("Hello, World!")

say_hello()  # Hello, World!

# 有参数函数
def greet(name):
    return f"Hello, {name}!"

print(greet("张三"))  # Hello, 张三!

# 多个参数
def add(a, b):
    return a + b

result = add(10, 20)
print(result)  # 30

3.2 函数命名规范

# ✅ 推荐:使用小写字母和下划线
def calculate_total():
    pass

def get_user_name():
    pass

def is_valid():
    pass

# ❌ 不推荐:驼峰命名(JavaScript 风格)
def calculateTotal():  # Python 不推荐
    pass

# ❌ 不推荐:大写开头(保留给类名)
def GetUserName():
    pass

3.3 函数文档字符串(Docstring)

def calculate_area(width, height):
    """
    计算矩形面积

    参数:
        width (float): 矩形宽度
        height (float): 矩形高度

    返回:
        float: 矩形面积

    示例:
        >>> calculate_area(10, 20)
        200
    """
    return width * height

# 查看函数文档
print(calculate_area.__doc__)
help(calculate_area)  # 显示详细帮助信息

🎯 四、参数类型注解

4.1 基本类型注解

Python 3.5+ 支持类型注解(Type Hints),类似 TypeScript:

# 基本类型注解
def add(a: int, b: int) -> int:
    """两个整数相加"""
    return a + b

def greet(name: str) -> str:
    """问候函数"""
    return f"Hello, {name}!"

def get_average(numbers: list) -> float:
    """计算平均值"""
    return sum(numbers) / len(numbers)

# 使用
result = add(10, 20)           # 30
msg = greet("Python")          # Hello, Python!
avg = get_average([1, 2, 3])   # 2.0

4.2 复杂类型注解

from typing import List, Dict, Tuple, Optional, Union

# 列表类型
def process_names(names: List[str]) -> List[str]:
    return [name.upper() for name in names]

# 字典类型
def get_user_info(user_id: int) -> Dict[str, str]:
    return {"name": "张三", "email": "zhang@example.com"}

# 元组类型
def get_coordinates() -> Tuple[float, float]:
    return (39.9, 116.4)

# 可选类型(可以是 None)
def find_user(user_id: int) -> Optional[str]:
    if user_id == 1:
        return "张三"
    return None

# 联合类型(多种类型之一)
def process_data(data: Union[str, int, float]) -> str:
    return str(data)

# Python 3.10+ 新语法(使用 | 代替 Union)
def process_value(value: str | int | float) -> str:
    return str(value)

4.3 类型注解的作用

# ⚠️ 注意:类型注解只是提示,不会强制检查!
def add(a: int, b: int) -> int:
    return a + b

# 这样调用不会报错,但类型检查工具会警告
result = add("hello", "world")  # 'helloworld'(字符串拼接)

# 使用类型检查工具(如 mypy)可以发现问题:
# $ mypy script.py
# error: Argument 1 to "add" has incompatible type "str"; expected "int"

📍 五、位置参数(Positional Arguments)

5.1 基本用法

位置参数必须按顺序传递,数量必须匹配:

def introduce(name, age, city):
    print(f"我叫{name},今年{age}岁,来自{city}")

# ✅ 正确:按顺序传递所有参数
introduce("张三", 25, "北京")
# 输出: 我叫张三,今年25岁,来自北京

# ❌ 错误:参数数量不匹配
introduce("张三", 25)
# TypeError: introduce() missing 1 required positional argument: 'city'

# ❌ 错误:参数过多
introduce("张三", 25, "北京", "程序员")
# TypeError: introduce() takes 3 positional arguments but 4 were given

5.2 位置参数的顺序很重要

def divide(a, b):
    return a / b

print(divide(10, 2))   # 5.0
print(divide(2, 10))   # 0.2(结果不同!)

5.3 与 JavaScript 的对比

// JavaScript - 参数可选,不会报错
function greet(name, age) {
  console.log(`${name}, ${age}`)
}

greet('张三') // 张三, undefined(不会报错)
greet('张三', 25, 'extra') // 张三, 25(忽略多余参数)
# Python - 参数严格,数量必须匹配
def greet(name, age):
    print(f"{name}, {age}")

greet("张三")         # ❌ TypeError: missing 1 required positional argument
greet("张三", 25, "extra")  # ❌ TypeError: takes 2 positional arguments but 3 were given

🔑 六、关键字参数(Keyword Arguments)

6.1 基本用法

关键字参数允许通过参数名传递,顺序无关:

def introduce(name, age, city):
    print(f"我叫{name},今年{age}岁,来自{city}")

# ✅ 使用关键字参数(顺序无关)
introduce(name="张三", age=25, city="北京")
introduce(age=25, city="北京", name="张三")  # 顺序不同,结果相同
introduce(city="北京", name="张三", age=25)

# ✅ 混合使用位置参数和关键字参数
introduce("张三", age=25, city="北京")
introduce("张三", city="北京", age=25)

# ❌ 错误:关键字参数必须在位置参数之后
introduce(name="张三", 25, "北京")  # SyntaxError

6.2 关键字参数的优势

# 代码可读性更好
def create_user(username, email, age, is_active, role):
    pass

# 不使用关键字参数(难以理解)
create_user("admin", "admin@example.com", 30, True, "admin")

# ✅ 使用关键字参数(一目了然)
create_user(
    username="admin",
    email="admin@example.com",
    age=30,
    is_active=True,
    role="admin"
)

6.3 强制关键字参数(Python 3+)

# 使用 * 强制后面的参数必须使用关键字传递
def create_user(username, *, email, age):
    print(f"{username}, {email}, {age}")

# ✅ 正确
create_user("admin", email="admin@example.com", age=30)

# ❌ 错误:email 和 age 必须使用关键字
create_user("admin", "admin@example.com", 30)
# TypeError: create_user() takes 1 positional argument but 3 were given

🎁 七、参数默认值

7.1 基本用法

def greet(name, message="你好"):
    return f"{message}, {name}!"

# 使用默认值
print(greet("张三"))              # 你好, 张三!

# 覆盖默认值
print(greet("张三", "早上好"))    # 早上好, 张三!
print(greet("张三", message="晚上好"))  # 晚上好, 张三!

7.2 默认值规则

# ✅ 正确:默认参数在后面
def func(a, b, c=10, d=20):
    pass

# ❌ 错误:默认参数在前面
def func(a=1, b, c):  # SyntaxError
    pass

# ✅ 正确:所有参数都有默认值
def func(a=1, b=2, c=3):
    pass

7.3 默认值陷阱(重要!)

# ❌ 危险:可变对象作为默认值
def add_item(item, items=[]):  # 危险!
    items.append(item)
    return items

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['a', 'b']  😱 不是 ['b']!
print(add_item("c"))  # ['a', 'b', 'c']

# ✅ 正确:使用 None 作为默认值
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['b']  ✅ 正确!
print(add_item("c"))  # ['c']

解释:

  • Python 的默认参数值在函数定义时计算一次
  • 如果默认值是可变对象(列表、字典),会在多次调用间共享
  • 应该使用 None 并在函数内部创建新对象

7.4 与 JavaScript 的对比

// JavaScript - 每次调用都重新计算默认值
function addItem(item, items = []) {
  items.push(item)
  return items
}

console.log(addItem('a')) // ['a']
console.log(addItem('b')) // ['b']  ✅ 每次都是新数组
# Python - 默认值只计算一次(陷阱!)
def add_item(item, items=[]):
    items.append(item)
    return items

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['a', 'b']  ⚠️ 不是新数组!

🌟 八、高级参数:不定长参数

8.1 *args - 接收任意数量的位置参数

# *args 将多余的位置参数收集到元组中
def sum_all(*args):
    """计算所有参数的和"""
    print(f"args 类型: {type(args)}")  # <class 'tuple'>
    print(f"args 内容: {args}")
    return sum(args)

# 可以传递任意数量的参数
print(sum_all(1, 2, 3))           # 6
print(sum_all(1, 2, 3, 4, 5))     # 15
print(sum_all())                  # 0
# *args 实战示例
def print_info(name, *hobbies):
    """打印姓名和爱好"""
    print(f"姓名: {name}")
    print(f"爱好: {', '.join(hobbies)}")

print_info("张三", "篮球", "游泳", "编程")
# 姓名: 张三
# 爱好: 篮球, 游泳, 编程

print_info("李四", "阅读")
# 姓名: 李四
# 爱好: 阅读

8.2 **kwargs - 接收任意数量的关键字参数

# **kwargs 将多余的关键字参数收集到字典中
def print_user_info(**kwargs):
    """打印用户信息"""
    print(f"kwargs 类型: {type(kwargs)}")  # <class 'dict'>
    print(f"kwargs 内容: {kwargs}")

    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_user_info(name="张三", age=25, city="北京")
# kwargs 类型: <class 'dict'>
# kwargs 内容: {'name': '张三', 'age': 25, 'city': '北京'}
# name: 张三
# age: 25
# city: 北京
# **kwargs 实战示例
def create_user(username, **attributes):
    """创建用户"""
    user = {"username": username}
    user.update(attributes)
    return user

user = create_user(
    "admin",
    email="admin@example.com",
    age=30,
    role="administrator",
    is_active=True
)
print(user)
# {'username': 'admin', 'email': 'admin@example.com', 'age': 30,
#  'role': 'administrator', 'is_active': True}

8.3 同时使用 *args 和 **kwargs

# 参数顺序:普通参数 → *args → **kwargs
def complex_func(a, b, *args, **kwargs):
    print(f"a = {a}")
    print(f"b = {b}")
    print(f"args = {args}")
    print(f"kwargs = {kwargs}")

complex_func(1, 2, 3, 4, 5, x=10, y=20)
# a = 1
# b = 2
# args = (3, 4, 5)
# kwargs = {'x': 10, 'y': 20}
# 完整参数顺序示例
def full_params(a, b=2, *args, c=3, **kwargs):
    """
    参数顺序:
    1. 位置参数: a
    2. 默认参数: b
    3. 不定长位置参数: *args
    4. 关键字参数: c
    5. 不定长关键字参数: **kwargs
    """
    print(f"a={a}, b={b}, args={args}, c={c}, kwargs={kwargs}")

full_params(1, 10, 20, 30, c=100, x=200, y=300)
# a=1, b=10, args=(20, 30), c=100, kwargs={'x': 200, 'y': 300}

8.4 参数解包(Unpacking)

# 使用 * 解包列表/元组
def add(a, b, c):
    return a + b + c

numbers = [1, 2, 3]
print(add(*numbers))  # 等价于 add(1, 2, 3)

# 使用 ** 解包字典
def greet(name, age, city):
    print(f"{name}, {age}岁, 来自{city}")

user = {"name": "张三", "age": 25, "city": "北京"}
greet(**user)  # 等价于 greet(name="张三", age=25, city="北京")

8.5 与 JavaScript 的对比

// JavaScript - 剩余参数(Rest Parameters)
function sum(...args) {
  return args.reduce((a, b) => a + b, 0)
}

sum(1, 2, 3) // 6

// JavaScript - 展开运算符(Spread Operator)
const numbers = [1, 2, 3]
add(...numbers)

const user = { name: '张三', age: 25 }
greet({ ...user })
# Python - *args 和 **kwargs
def sum_all(*args):
    return sum(args)

sum_all(1, 2, 3)  # 6

# Python - 解包
numbers = [1, 2, 3]
add(*numbers)

user = {"name": "张三", "age": 25}
greet(**user)

📖 九、函数文档(Docstring)

9.1 基本文档字符串

def add(a, b):
    """两个数相加"""
    return a + b

# 查看文档
print(add.__doc__)  # 两个数相加

9.2 详细文档字符串(推荐格式)

def calculate_bmi(weight, height):
    """
    计算身体质量指数(BMI)

    BMI = 体重(kg) / 身高(m)²

    参数:
        weight (float): 体重,单位:千克
        height (float): 身高,单位:米

    返回:
        float: BMI 值

    异常:
        ValueError: 当 weight 或 height 小于等于 0 时

    示例:
        >>> calculate_bmi(70, 1.75)
        22.857142857142858

        >>> calculate_bmi(60, 1.65)
        22.03856749311295
    """
    if weight <= 0 or height <= 0:
        raise ValueError("体重和身高必须大于 0")

    return weight / (height ** 2)

# 查看文档
help(calculate_bmi)

9.3 Google 风格文档字符串

def send_email(to, subject, body, cc=None, bcc=None):
    """发送电子邮件

    Args:
        to (str): 收件人邮箱地址
        subject (str): 邮件主题
        body (str): 邮件正文
        cc (list, optional): 抄送列表. Defaults to None.
        bcc (list, optional): 密送列表. Defaults to None.

    Returns:
        bool: 发送成功返回 True,失败返回 False

    Raises:
        ValueError: 邮箱地址格式不正确
        ConnectionError: 无法连接到邮件服务器

    Examples:
        >>> send_email("user@example.com", "测试", "这是测试邮件")
        True

        >>> send_email("user@example.com", "通知", "内容", cc=["cc@example.com"])
        True
    """
    # 函数实现
    pass

9.4 NumPy 风格文档字符串

def linear_regression(x, y):
    """
    简单线性回归分析

    Parameters
    ----------
    x : array_like
        自变量数据
    y : array_like
        因变量数据

    Returns
    -------
    slope : float
        回归直线斜率
    intercept : float
        回归直线截距

    See Also
    --------
    polynomial_regression : 多项式回归

    Notes
    -----
    使用最小二乘法拟合直线

    Examples
    --------
    >>> x = [1, 2, 3, 4, 5]
    >>> y = [2, 4, 6, 8, 10]
    >>> slope, intercept = linear_regression(x, y)
    >>> slope
    2.0
    """
    # 函数实现
    pass

🔍 十、函数内省(Introspection)

10.1 查看函数属性

def greet(name: str, age: int = 18) -> str:
    """问候函数"""
    return f"Hello, {name}! You are {age} years old."

# 函数名称
print(greet.__name__)  # greet

# 函数文档
print(greet.__doc__)   # 问候函数

# 函数模块
print(greet.__module__)  # __main__

# 函数注解
print(greet.__annotations__)
# {'name': <class 'str'>, 'age': <class 'int'>, 'return': <class 'str'>}

# 函数默认值
print(greet.__defaults__)  # (18,)

# 函数代码对象
print(greet.__code__)
print(greet.__code__.co_varnames)  # ('name', 'age') - 参数名
print(greet.__code__.co_argcount)  # 2 - 参数数量

10.2 使用 inspect 模块

import inspect

def calculate(a: int, b: int, op: str = "add") -> int:
    """计算函数"""
    if op == "add":
        return a + b
    elif op == "subtract":
        return a - b
    return 0

# 获取函数签名
sig = inspect.signature(calculate)
print(sig)  # (a: int, b: int, op: str = 'add') -> int

# 获取参数信息
for name, param in sig.parameters.items():
    print(f"参数: {name}")
    print(f"  类型注解: {param.annotation}")
    print(f"  默认值: {param.default}")
    print()

# 获取源代码
print(inspect.getsource(calculate))

# 判断是否为函数
print(inspect.isfunction(calculate))  # True

# 获取文档字符串
print(inspect.getdoc(calculate))  # 计算函数

10.3 实用工具函数

import inspect

def show_function_info(func):
    """显示函数详细信息"""
    print(f"函数名: {func.__name__}")
    print(f"文档: {func.__doc__}")
    print(f"\n签名: {inspect.signature(func)}")

    print("\n参数详情:")
    for name, param in inspect.signature(func).parameters.items():
        info = f"  {name}"
        if param.annotation != inspect.Parameter.empty:
            info += f" : {param.annotation.__name__}"
        if param.default != inspect.Parameter.empty:
            info += f" = {param.default}"
        print(info)

    ret_annotation = inspect.signature(func).return_annotation
    if ret_annotation != inspect.Signature.empty:
        print(f"\n返回类型: {ret_annotation.__name__}")

# 使用
def greet(name: str, age: int = 18) -> str:
    """问候用户"""
    return f"Hello, {name}!"

show_function_info(greet)
# 函数名: greet
# 文档: 问候用户
#
# 签名: (name: str, age: int = 18) -> str
#
# 参数详情:
#   name : str
#   age : int = 18
#
# 返回类型: str

🔙 十一、函数返回值

11.1 基本返回值

# 返回单个值
def add(a, b):
    return a + b

result = add(10, 20)
print(result)  # 30

# 无返回值(默认返回 None)
def greet(name):
    print(f"Hello, {name}!")

result = greet("张三")  # Hello, 张三!
print(result)           # None

11.2 返回多个值(元组解包)

# 返回多个值(实际返回元组)
def get_user_info():
    name = "张三"
    age = 25
    city = "北京"
    return name, age, city  # 返回元组

# 接收所有返回值
result = get_user_info()
print(result)  # ('张三', 25, '北京')
print(type(result))  # <class 'tuple'>

# ✅ 元组解包(推荐)
name, age, city = get_user_info()
print(name)   # 张三
print(age)    # 25
print(city)   # 北京

# 部分解包(使用 _)
name, _, city = get_user_info()  # 忽略 age
print(name, city)  # 张三 北京

11.3 返回字典(更清晰)

# 返回字典(键值对更清晰)
def get_user_info():
    return {
        "name": "张三",
        "age": 25,
        "city": "北京",
        "email": "zhang@example.com"
    }

user = get_user_info()
print(user["name"])  # 张三
print(user["age"])   # 25

11.4 提前返回(Early Return)

# ✅ 使用提前返回简化逻辑
def divide(a, b):
    """除法运算,处理除零情况"""
    if b == 0:
        return None  # 提前返回
    return a / b

print(divide(10, 2))  # 5.0
print(divide(10, 0))  # None

# ✅ 多个提前返回
def get_grade(score):
    """根据分数返回等级"""
    if score >= 90:
        return "A"
    if score >= 80:
        return "B"
    if score >= 60:
        return "C"
    return "D"

print(get_grade(95))  # A
print(get_grade(75))  # C

11.5 返回函数(高阶函数)

# 返回函数
def create_multiplier(n):
    """创建一个乘法函数"""
    def multiplier(x):
        return x * n
    return multiplier

# 使用
double = create_multiplier(2)
triple = create_multiplier(3)

print(double(5))   # 10
print(triple(5))   # 15

11.6 与 JavaScript 的对比

// JavaScript - 返回多个值需要使用对象或数组
function getUserInfo() {
  return {
    name: '张三',
    age: 25,
    city: '北京',
  }
}

const { name, age, city } = getUserInfo() // 解构赋值
# Python - 自然支持多返回值(元组)
def get_user_info():
    return "张三", 25, "北京"

name, age, city = get_user_info()  # 元组解包

🎭 十二、匿名函数(Lambda)

12.1 基本语法

# 普通函数
def add(a, b):
    return a + b

# 等价的 lambda 函数
add = lambda a, b: a + b

print(add(10, 20))  # 30

lambda 语法:

lambda 参数1, 参数2, ...: 表达式

12.2 lambda 的特点

# ✅ 适用场景:简单的单行函数
square = lambda x: x ** 2
print(square(5))  # 25

# ✅ 作为参数传递给其他函数
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

# ❌ 不适合:复杂逻辑(可读性差)
# 不推荐
calc = lambda x, y: x + y if x > y else x - y

# ✅ 推荐:使用普通函数
def calc(x, y):
    if x > y:
        return x + y
    else:
        return x - y

12.3 lambda 实战应用

# 排序
students = [
    {"name": "张三", "score": 85},
    {"name": "李四", "score": 92},
    {"name": "王五", "score": 78}
]

# 按分数排序
sorted_students = sorted(students, key=lambda s: s["score"])
print(sorted_students)
# [{'name': '王五', 'score': 78}, {'name': '张三', 'score': 85},
#  {'name': '李四', 'score': 92}]

# 过滤
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # [2, 4, 6, 8, 10]

# 映射
words = ["hello", "world", "python"]
upper_words = list(map(lambda w: w.upper(), words))
print(upper_words)  # ['HELLO', 'WORLD', 'PYTHON']

12.4 lambda vs 普通函数

特性lambda普通函数 def
语法lambda x: x * 2def f(x): return x * 2
函数名匿名(无名称)必须有名称
代码行数只能单行表达式可以多行
文档字符串不支持支持
适用场景简单、临时的小函数复杂逻辑、可复用函数
调试较难容易

12.5 与 JavaScript 箭头函数对比

// JavaScript - 箭头函数
const add = (a, b) => a + b
const square = (x) => x * 2

// 多行箭头函数
const greet = (name) => {
  const message = `Hello, ${name}!`
  return message
}

// 作为回调
numbers.map((x) => x * 2)
# Python - lambda 函数
add = lambda a, b: a + b
square = lambda x: x * 2

# ❌ 不支持多行(必须用 def)
def greet(name):
    message = f"Hello, {name}!"
    return message

# 作为参数
list(map(lambda x: x * 2, numbers))

🎨 十三、实战场景

13.1 装饰器模式(高级)

import time

def timer(func):
    """计时装饰器"""
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} 耗时: {end - start:.4f} 秒")
        return result
    return wrapper

@timer
def slow_function():
    """模拟耗时操作"""
    time.sleep(1)
    return "完成"

result = slow_function()
# slow_function 耗时: 1.0012 秒

13.2 闭包(Closure)

def create_counter():
    """创建计数器(闭包)"""
    count = 0

    def increment():
        nonlocal count  # 修改外部变量
        count += 1
        return count

    return increment

counter1 = create_counter()
counter2 = create_counter()

print(counter1())  # 1
print(counter1())  # 2
print(counter2())  # 1(独立的计数器)
print(counter1())  # 3

13.3 函数工厂

def create_validator(min_value, max_value):
    """创建验证器函数"""
    def validate(value):
        if value < min_value:
            return f"值太小,最小值为 {min_value}"
        if value > max_value:
            return f"值太大,最大值为 {max_value}"
        return "验证通过"
    return validate

# 创建不同的验证器
age_validator = create_validator(0, 150)
score_validator = create_validator(0, 100)

print(age_validator(25))    # 验证通过
print(age_validator(200))   # 值太大,最大值为 150
print(score_validator(95))  # 验证通过
print(score_validator(105)) # 值太大,最大值为 100

💡 十四、最佳实践

14.1 函数设计原则

# ✅ 单一职责:一个函数只做一件事
def calculate_total(prices):
    """计算总价"""
    return sum(prices)

def apply_discount(total, discount):
    """应用折扣"""
    return total * (1 - discount)

# ❌ 避免:函数做太多事
def calculate_and_format_total(prices, discount, currency="¥"):
    total = sum(prices)
    discounted = total * (1 - discount)
    return f"{currency}{discounted:.2f}"

14.2 函数命名

# ✅ 动词开头,清晰描述功能
def get_user_name():
    pass

def calculate_total():
    pass

def is_valid():
    pass

def has_permission():
    pass

# ❌ 避免:模糊的名称
def process():  # 太笼统
    pass

def do_stuff():  # 不清晰
    pass

14.3 参数数量

# ✅ 参数不要太多(建议 ≤ 5 个)
def create_user(username, email, password):
    pass

# ❌ 参数太多,考虑使用字典或类
def create_user(username, email, password, first_name, last_name,
                age, city, country, phone, address):
    pass

# ✅ 改进:使用字典
def create_user(username, email, password, **profile):
    pass

create_user(
    "admin",
    "admin@example.com",
    "secret",
    first_name="张",
    last_name="三",
    age=25
)

14.4 使用类型注解

# ✅ 添加类型注解,提高可读性
from typing import List, Dict, Optional

def calculate_average(numbers: List[float]) -> float:
    """计算平均值"""
    return sum(numbers) / len(numbers)

def find_user(user_id: int) -> Optional[Dict[str, str]]:
    """查找用户"""
    # 返回用户字典或 None
    pass

14.5 错误处理

# ✅ 明确的错误处理
def divide(a: float, b: float) -> float:
    """除法运算"""
    if b == 0:
        raise ValueError("除数不能为 0")
    return a / b

# ✅ 使用自定义异常
class InvalidEmailError(Exception):
    """无效的邮箱地址"""
    pass

def validate_email(email: str) -> bool:
    if "@" not in email:
        raise InvalidEmailError(f"无效的邮箱: {email}")
    return True

📚 十五、总结

核心要点

  1. 函数定义:使用 def 关键字,遵循命名规范
  2. 参数类型
    • 位置参数:按顺序传递,数量必须匹配
    • 关键字参数:通过名称传递,顺序无关
    • 默认参数:提供默认值,可选参数
    • *args:接收任意数量位置参数
    • **kwargs:接收任意数量关键字参数
  3. 类型注解:提高代码可读性和可维护性
  4. 文档字符串:详细描述函数功能、参数、返回值
  5. 返回值:可返回单值、多值(元组)、字典、函数等
  6. Lambda:适合简单的单行函数
  7. 函数内省:使用 inspect 模块分析函数

Python vs JavaScript 函数对比

特性JavaScriptPython
定义function / =>def
参数检查不检查严格检查数量
默认参数每次重新计算定义时计算一次(陷阱)
不定长参数...args*args, **kwargs
解包... spread*, **
匿名函数箭头函数(多行支持)lambda(仅单行)
类型注解TypeScript原生支持
文档JSDocdocstring

最佳实践清单

  • 使用类型注解提高代码质量
  • 编写文档字符串说明函数用途
  • 遵循单一职责原则
  • 合理使用默认参数(避免可变对象陷阱)
  • ✅ **使用 *args 和 **kwargs** 提高灵活性
  • 函数名使用动词,清晰描述功能
  • 保持参数数量在 5 个以内
  • 提前返回简化逻辑
  • ❌ 避免函数过长(建议 ≤ 50 行)
  • ❌ 避免过深嵌套(建议 ≤ 3 层)

常用代码模板

# 📝 基本函数模板
def function_name(param1: type1, param2: type2 = default) -> return_type:
    """
    函数描述

    Args:
        param1: 参数1描述
        param2: 参数2描述

    Returns:
        返回值描述

    Raises:
        ExceptionType: 异常描述
    """
    # 函数实现
    return result

# 🌟 万能参数模板
def flexible_func(*args, **kwargs):
    """接收任意参数的函数"""
    print(f"位置参数: {args}")
    print(f"关键字参数: {kwargs}")

# 🎭 装饰器模板
def decorator(func):
    """装饰器"""
    def wrapper(*args, **kwargs):
        # 前置处理
        result = func(*args, **kwargs)
        # 后置处理
        return result
    return wrapper

本文适合前端开发者快速掌握 Python 函数,从基础到高级,涵盖参数、文档、返回值、Lambda 等核心概念。记住:善用类型注解和文档字符串,让代码更易维护 🚀