Python 函数:从"重复劳动"到"一键搞定"的编程革命
引言:为什么需要函数?
想象你是一家奶茶店的老板,每天要制作 100 杯珍珠奶茶。如果每杯都要手动完成:烧水 → 泡茶 → 加奶 → 加糖 → 加珍珠 → 封口,你会累死。
更好的办法是:制定一个标准配方(函数),每次只需要按一下按钮(调用函数),机器自动完成所有步骤。
在编程世界里,函数就是这个"标准配方"。它把一段重复使用的代码封装起来,起个名字,以后只需写名字就能执行整段代码。
今天,我们将彻底掌握函数的精髓,让你的代码从"手工作坊"升级为"自动化工厂"。
一、从重复到抽象:函数的诞生
1.1 问题的出现:代码重复
假设你要计算 3 个圆的面积:
r1 = 12.34
r2 = 9.08
r3 = 73.1
s1 = 3.14 * r1 * r1
s2 = 3.14 * r2 * r2
s3 = 3.14 * r3 * r3问题 1:3.14 * x * x 写了 3 遍,很麻烦。
问题 2:如果要提高精度,把 3.14 改成 3.14159265359,需要改 3 个地方。如果计算 100 个圆呢?改 100 个地方?
1.2 函数的解决方案
def area_of_circle(r):
return 3.14159265359 * r * r
s1 = area_of_circle(12.34)
s2 = area_of_circle(9.08)
s3 = area_of_circle(73.1)生活化理解:函数就像奶茶店的"标准配方卡"——只需要写一次配方,店员每次按配方操作即可。要改配方?只改卡片,所有奶茶自动更新。
1.3 函数的核心价值:抽象
抽象是计算机科学的核心概念。它让我们忽略底层细节,关注高层逻辑。
数学中的抽象:
- 不抽象:
1 + 2 + 3 + ... + 100(写 100 个数字) - 抽象后:
∑(n=1 to 100) n(一个符号搞定)
编程中的抽象:
- 不抽象:每次写
3.14 * r * r - 抽象后:
area_of_circle(r)
生活化理解:就像开车——你不需要懂发动机原理,只需要会踩油门。函数就是你的"油门",踩下去就走,不用管内部怎么运转。
二、函数的定义与调用
2.1 定义函数:def 关键字
def 函数名(参数):
"""函数文档说明(可选)"""
函数体
return 返回值逐部分解析:
def greet(name): # def + 函数名 + 参数列表
"""向指定的人打招呼""" # 文档字符串(可选)
message = f'你好,{name}!' # 函数体
return message # 返回值(可选)2.2 调用函数:写名字就行
# 定义
def greet(name):
return f'你好,{name}!'
# 调用
result = greet('张三')
print(result) # 你好,张三!
print(greet('李四')) # 你好,李四!生活化理解:定义函数像"注册公司"——准备好所有资源;调用函数像"开始营业"——真正使用这些资源。
2.3 函数的组成要素
| 要素 | 说明 | 示例 |
|---|---|---|
| 函数名 | 标识符,遵循命名规则 | greet, calculate_area |
| 参数 | 输入,可以有多个或没有 | (name), (x, y), () |
| 函数体 | 实现功能的代码块 | 缩进的代码 |
| 返回值 | 输出,用 return 返回 | return result |
| 文档字符串 | 说明函数功能 | """这是说明""" |
三、参数:函数的"输入口"
3.1 位置参数
def introduce(name, age, city):
return f'{name},{age}岁,来自{city}'
# 按位置传参
print(introduce('张三', 25, '北京'))
# 张三,25岁,来自北京注意:顺序很重要!
print(introduce('北京', 25, '张三')) # 顺序错了,结果乱了3.2 默认参数
def introduce(name, age, city='北京'):
return f'{name},{age}岁,来自{city}'
# 不传 city,用默认值
print(introduce('张三', 25)) # 张三,25岁,来自北京
# 传 city,覆盖默认值
print(introduce('李四', 30, '上海')) # 李四,30岁,来自上海生活化理解:默认参数像"默认配置"——买手机默认 128G 存储,你可以加钱上 256G。
3.3 关键字参数
def introduce(name, age, city):
return f'{name},{age}岁,来自{city}'
# 按名字传参,不用管顺序
print(introduce(city='北京', name='张三', age=25))
# 张三,25岁,来自北京优点:
- 不用记参数顺序
- 代码更清晰
- 可以跳过有默认值的参数
3.4 可变参数:*args
def sum_all(*numbers):
total = 0
for n in numbers:
total = total + n
return total
print(sum_all(1, 2)) # 3
print(sum_all(1, 2, 3, 4, 5)) # 15
print(sum_all()) # 0生活化理解:*numbers 像"任意数量的包裹"——不管寄几个,我都收。
3.5 关键字可变参数:**kwargs
def print_info(**info):
for key, value in info.items():
print(f'{key}: {value}')
print_info(name='张三', age=25, city='北京')
# name: 张三
# age: 25
# city: 北京生活化理解:**info 像"任意数量的标签"——不管贴几个标签,我都认。
3.6 参数组合
def complex_func(a, b, c=0, *args, **kwargs):
print(f'a={a}, b={b}, c={c}')
print(f'args={args}')
print(f'kwargs={kwargs}')
complex_func(1, 2, 3, 4, 5, x=6, y=7)
# a=1, b=2, c=3
# args=(4, 5)
# kwargs={'x': 6, 'y': 7}顺序规则:位置参数 → 默认参数 → *args → **kwargs
四、返回值:函数的"输出口"
4.1 单个返回值
def square(x):
return x * x
result = square(5)
print(result) # 254.2 多个返回值
def get_user():
name = '张三'
age = 25
city = '北京'
return name, age, city # 返回 tuple
# 解包接收
n, a, c = get_user()
print(n) # 张三
print(a) # 254.3 没有返回值
def say_hello():
print('Hello!')
# 没有 return,默认返回 None
result = say_hello()
print(result) # None4.4 return 的提前退出
def check_age(age):
if age < 0:
return '年龄不能为负'
if age < 18:
return '未成年'
return '成年'
print(check_age(-5)) # 年龄不能为负
print(check_age(10)) # 未成年
print(check_age(20)) # 成年注意:一旦执行 return,函数立即结束,后面的代码不再执行。
五、作用域:变量的"活动范围"
5.1 局部变量
def my_func():
x = 10 # 局部变量,只在函数内有效
print(x)
my_func() # 10
print(x) # NameError: name 'x' is not defined生活化理解:局部变量像"家里的钥匙"——只在家里有效,出门就用不了。
5.2 全局变量
x = 10 # 全局变量
def my_func():
print(x) # 可以读取全局变量
my_func() # 105.3 修改全局变量:global 关键字
count = 0
def increment():
global count # 声明使用全局变量
count = count + 1
increment()
print(count) # 1注意:尽量不用 global,函数应该通过参数和返回值交流,而不是直接改全局变量。
六、常见误区与陷阱
6.1 误区一:忘记 return
# ❌ 错误:没有 return,默认返回 None
def add(a, b):
a + b
result = add(1, 2)
print(result) # None(不是3!)
# ✅ 正确
def add(a, b):
return a + b6.2 误区二:默认参数用可变对象
# ❌ 危险:默认参数只创建一次,多次调用共享
def add_item(item, items=[]):
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2](不是预期的 [2]!)
# ✅ 正确:用 None 作为默认值
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items6.3 误区三:函数名覆盖内置函数
# ❌ 危险:覆盖内置函数
def list():
return [1, 2, 3]
my_list = list() # 调用的是自定义函数,不是内置 list()
my_list.append(4) # AttributeError
# ✅ 正确:避免使用内置函数名
def my_list_func():
return [1, 2, 3]6.4 误区四:参数顺序错误
# ❌ 错误:默认参数必须在位置参数后面
def func(a=1, b):
pass # SyntaxError
# ✅ 正确
def func(a, b=1):
pass七、实战案例
案例 1:BMI 计算器(函数版)
def calculate_bmi(height, weight):
"""计算 BMI 指数"""
return weight / (height ** 2)
def classify_bmi(bmi):
"""根据 BMI 分类"""
if bmi < 18.5:
return '过轻'
elif bmi < 25:
return '正常'
elif bmi < 28:
return '过重'
elif bmi < 32:
return '肥胖'
else:
return '严重肥胖'
def main():
height = float(input('身高(米):'))
weight = float(input('体重(千克):'))
bmi = calculate_bmi(height, weight)
category = classify_bmi(bmi)
print(f'你的 BMI:{bmi:.1f},属于:{category}')
main()案例 2:简易记账本
def create_account():
"""创建账户"""
return {'balance': 0, 'transactions': []}
def deposit(account, amount):
"""存款"""
account['balance'] += amount
account['transactions'].append(f'存入 {amount} 元')
return account['balance']
def withdraw(account, amount):
"""取款"""
if amount > account['balance']:
return '余额不足'
account['balance'] -= amount
account['transactions'].append(f'取出 {amount} 元')
return account['balance']
def print_statement(account):
"""打印账单"""
print(f'当前余额:{account["balance"]} 元')
print('交易记录:')
for t in account['transactions']:
print(f' - {t}')
# 使用
acc = create_account()
deposit(acc, 1000)
withdraw(acc, 300)
print_statement(acc)案例 3:密码强度检查器
def check_length(password):
"""检查长度"""
return len(password) >= 8
def has_uppercase(password):
"""检查是否包含大写字母"""
return any(c.isupper() for c in password)
def has_lowercase(password):
"""检查是否包含小写字母"""
return any(c.islower() for c in password)
def has_digit(password):
"""检查是否包含数字"""
return any(c.isdigit() for c in password)
def check_password_strength(password):
"""综合检查密码强度"""
score = 0
if check_length(password):
score += 1
if has_uppercase(password):
score += 1
if has_lowercase(password):
score += 1
if has_digit(password):
score += 1
if score == 4:
return '强'
elif score == 3:
return '中'
else:
return '弱'
# 测试
print(check_password_strength('abc')) # 弱
print(check_password_strength('Abc123')) # 中
print(check_password_strength('Abc12345')) # 强八、动手练习
练习 1:写一个函数,计算 1 到 n 的和
def sum_to_n(n):
total = 0
for i in range(1, n + 1):
total += i
return total
print(sum_to_n(100)) # 5050练习 2:写一个函数,判断一个数是否为素数
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
print(is_prime(7)) # True
print(is_prime(8)) # False总结
| 概念 | 核心要点 |
|---|---|
| 函数定义 | def 函数名(参数): |
| 函数调用 | 函数名(实参) |
| 参数类型 | 位置参数、默认参数、关键字参数、*args、**kwargs |
| 返回值 | return 返回结果,无 return 返回 None |
| 作用域 | 局部变量只在函数内有效,全局变量用 global 声明 |
| 核心价值 | 抽象、复用、模块化 |
记住:函数是你的标准配方——定义一次,调用多次。参数是输入口,返回值是输出口,抽象是核心价值。
本文基于廖雪峰 Python 教程重新撰写,补充了大量背景知识、生活化类比和实战场景。推荐继续阅读:调用函数