🐍 前端开发 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 基本语法对比
| 特性 | JavaScript | Python |
|---|---|---|
| 定义关键字 | function 或 => | def |
| 参数类型注解 | TypeScript 支持 | 原生支持 |
| 默认参数 | function(a = 1) | def func(a=1): |
| 不定长参数 | ...args | *args, **kwargs |
| 匿名函数 | (x) => x * 2 | lambda 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 * 2 | def 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
📚 十五、总结
核心要点
- 函数定义:使用
def关键字,遵循命名规范 - 参数类型:
- 位置参数:按顺序传递,数量必须匹配
- 关键字参数:通过名称传递,顺序无关
- 默认参数:提供默认值,可选参数
*args:接收任意数量位置参数**kwargs:接收任意数量关键字参数
- 类型注解:提高代码可读性和可维护性
- 文档字符串:详细描述函数功能、参数、返回值
- 返回值:可返回单值、多值(元组)、字典、函数等
- Lambda:适合简单的单行函数
- 函数内省:使用
inspect模块分析函数
Python vs JavaScript 函数对比
| 特性 | JavaScript | Python |
|---|---|---|
| 定义 | function / => | def |
| 参数检查 | 不检查 | 严格检查数量 |
| 默认参数 | 每次重新计算 | 定义时计算一次(陷阱) |
| 不定长参数 | ...args | *args, **kwargs |
| 解包 | ... spread | *, ** |
| 匿名函数 | 箭头函数(多行支持) | lambda(仅单行) |
| 类型注解 | TypeScript | 原生支持 |
| 文档 | JSDoc | docstring |
最佳实践清单
- ✅ 使用类型注解提高代码质量
- ✅ 编写文档字符串说明函数用途
- ✅ 遵循单一职责原则
- ✅ 合理使用默认参数(避免可变对象陷阱)
- ✅ **使用 *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 等核心概念。记住:善用类型注解和文档字符串,让代码更易维护! 🚀