当前位置:首页>python>Python 零基础100天—Day13 函数基础

Python 零基础100天—Day13 函数基础

  • 2026-10-11 08:04:57
Python 零基础100天—Day13 函数基础

🐍 函数基础 — 代码的乐高积木

🕐 预计用时:2-3 小时 | 🎯 目标:掌握 def、参数类型、return 和文档字符串


📖 今日目录

  1. 为什么要用函数?
  2. 定义和调用函数
  3. 参数:位置参数
  4. 参数:默认值
  5. 参数:关键字参数
  6. return 返回值
  7. 文档字符串(docstring)
  8. 函数的返回值进阶
  9. 实战练习
  10. 今日小结

1. 为什么要用函数?

函数就是"打包好的代码"——写一次,用无数次。

想象你每天早上要做三件事:泡咖啡、烤面包、煎鸡蛋。没有函数的话,每天都要重复写一遍步骤。有了函数,你只需要说一声"做早餐",三件事自动完成。

# ❌ 没有函数:重复代码print("=" * 30)print("欢迎来到商店A")print("=" * 30)# ... 100行代码后 ...print("=" * 30)print("欢迎来到商店B")print("=" * 30)# ✅ 有函数:复用代码def print_welcome(name):    print("=" * 30)    print(f"欢迎来到{name}")    print("=" * 30)print_welcome("商店A")print_welcome("商店B")
对比
不用函数
用函数
代码复用
复制粘贴
调用函数
修改维护
改 N 处
改 1 处
可读性
一大坨代码
见名知意
调试
到处找 bug
定位到函数

2. 定义和调用函数

📖 基本语法

# 定义函数def greet():    print("你好!")    print("欢迎光临!")# 调用函数greet()   # 你好! 欢迎光临!greet()   # 可以调用无数次

函数定义的四个要素:

要素
说明
示例
def
关键字,声明定义函数
def greet():
函数名
遵循变量命名规则
greet
参数
括号里的输入(可以为空)
(name)
函数体
缩进的代码块
print("hi")
# 定义 vs 调用def say_hello(name):       # ← 定义(不执行代码)    print(f"Hello, {name}!")say_hello("张三")           # ← 调用(才执行代码)say_hello("李四")           # ← 再次调用

💡 常见新手错误:定义了函数但忘了调用。def greet(): print("hi") ← 这行什么都不会打印!必须写 greet() 才会执行。


3. 参数:位置参数

位置参数是最基本的参数类型——按顺序传入。

# 一个参数def greet(name):    print(f"你好,{name}!")greet("张三")   # 你好,张三!greet("李四")   # 你好,李四!# 多个参数def introduce(name, age, city):    print(f"我叫{name},{age}岁,来自{city}")introduce("张三", 25, "北京")   # 顺序很重要!introduce("北京", 25, "张三")   # ❌ 顺序错了,意思全变

🔢 参数数量检查

def add(a, b):    return a + badd(1, 2)      # ✅ 正确# add(1)       # ❌ TypeError: 缺少参数# add(1, 2, 3) # ❌ TypeError: 参数太多

4. 参数:默认值

给参数一个"备胎"值——调用时不传就用默认值。

# 有默认值的参数def greet(name, greeting="你好"):    print(f"{greeting},{name}!")greet("张三")              # 你好,张三!(用默认值)greet("张三", "早上好")     # 早上好,张三!(用传入的值)# 多个默认值def create_user(name, age=18, city="未知", role="学生"):    print(f"用户: {name}, 年龄: {age}, 城市: {city}, 角色: {role}")create_user("张三")                          # 全部用默认值create_user("李四", 25)                      # 只改年龄create_user("王五", city="上海")             # 跳过 age,改城市(关键字参数)create_user("赵六", 30, "广州", "老师")      # 全部自定义

⚠️ 重要规则:有默认值的参数必须放在没有默认值的参数后面!

def greet(name, greeting="你好"):   # ✅ 正确def greet(greeting="你好", name):   # ❌ SyntaxError!

原因:Python 从左到右匹配参数,如果默认值在前面,它不知道哪个值传给谁。

⚠️ 默认值的陷阱:可变对象

# ❌ 危险:默认值用可变对象(列表、字典)def add_item(item, items=[]):    items.append(item)    return itemsprint(add_item("苹果"))   # ['苹果']print(add_item("香蕉"))   # ['苹果', '香蕉'] ← 咩?!print(add_item("橘子"))   # ['苹果', '香蕉', '橘子'] ← 更离谱!# 原因:默认列表只创建一次,所有调用共享同一个列表对象
# ✅ 正确写法:用 None 作为默认值def add_item(item, items=None):    if items is None:        items = []       # 每次调用都创建新列表    items.append(item)    return itemsprint(add_item("苹果"))   # ['苹果']print(add_item("香蕉"))   # ['香蕉'] ← 正确了!

💡 黄金法则:函数的默认值永远不要用可变对象(列表、字典、集合)。用 None 代替,在函数体内再创建。


5. 参数:关键字参数

关键字参数让你可以"指名道姓"地传值,不用管顺序。

def create_profile(name, age, city, hobby):    print(f"姓名: {name}, 年龄: {age}, 城市: {city}, 爱好: {hobby}")# 位置参数:按顺序create_profile("张三", 25, "北京", "编程")# 关键字参数:按名字create_profile(hobby="编程", name="张三", city="北京", age=25)# 混合使用:位置参数在前,关键字参数在后create_profile("张三", 25, hobby="编程", city="北京")

💡 什么时候用关键字参数?1. 参数多、容易搞混顺序时2. 调用不常见的函数时(提高可读性)3. 有默认值、只想改其中几个时


6. return 返回值

print 是给人看的,return 是给程序用的。

# 没有 return 的函数,返回 Nonedef greet(name):    print(f"你好,{name}")result = greet("张三")    # 打印: 你好,张三print(result)              # None ← 函数没有 return,返回 None# 有 return 的函数,返回值def add(a, b):    return a + bresult = add(3, 5)print(result)              # 8 ← return 的值被拿到

📦 return 的用法

# 返回单个值def square(n):    return n * nprint(square(5))  # 25# 返回多个值(实际返回一个元组)def min_max(numbers):    return min(numbers), max(numbers)lo, hi = min_max([3, 1, 4, 1, 5, 9])print(f"最小: {lo}, 最大: {hi}")   # 最小: 1, 最大: 9# 返回不同类型的值def divide(a, b):    if b == 0:        return None           # 除以零返回 None    return a / b              # 正常返回结果print(divide(10, 3))   # 3.333...print(divide(10, 0))   # None# 提前返回(early return)def check_age(age):    if age < 0:        return "年龄不能为负数"   # 提前退出    if age < 18:        return "未成年"    if age < 65:        return "成年人"    return "老年人"print(check_age(25))   # 成年人print(check_age(-5))   # 年龄不能为负数

💡 print vs return 区别:

print
return
作用
在屏幕上显示
把值交给调用者
能存变量
❌(存的是 None)
✅
能继续计算
❌
✅
用途
调试、展示
函数输出

7. 文档字符串(docstring)

docstring 是函数的"说明书"——告诉别人(和未来的自己)这个函数干什么。

def calculate_bmi(weight, height):    """    计算 BMI(身体质量指数)    参数:        weight (float): 体重,单位:千克        height (float): 身高,单位:米    返回:        float: BMI 值    示例:        >>> calculate_bmi(70, 1.75)        22.86    """    bmi = weight / (height ** 2)    return round(bmi, 2)# 查看文档help(calculate_bmi)print(calculate_bmi.__doc__)# 使用result = calculate_bmi(70, 1.75)print(f"BMI: {result}")   # BMI: 22.86

📝 docstring 的格式

# 单行 docstring(简单函数)def double(n):    """返回 n 的两倍。"""    return n * 2# 多行 docstring(复杂函数)def process_data(data, threshold=0.5, mode="filter"):    """    处理数据并返回结果。    根据阈值和模式对数据进行过滤或转换。    Args:        data: 输入数据列表        threshold: 阈值,默认 0.5        mode: 处理模式,'filter' 或 'transform'    Returns:        list: 处理后的数据    Raises:        ValueError: 当 mode 不是 'filter' 或 'transform' 时    """    if mode not in ("filter", "transform"):        raise ValueError(f"无效模式: {mode}")    if mode == "filter":        return [x for x in data if x > threshold]    else:        return [x * threshold for x in data]

💡 好的 docstring 三要素:1. 一句话描述:这个函数做什么2. 参数说明:每个参数是什么意思3. 返回值:返回什么养成写 docstring 的习惯,三个月后的你会感谢现在的自己。


8. 函数的返回值进阶

🔄 返回多个值

# Python 可以一次返回多个值(本质是返回元组)def get_name_age():    return "张三", 25result = get_name_age()print(result)        # ('张三', 25)  ← 元组print(type(result))  # <class 'tuple'># 解包接收name, age = get_name_age()print(name)   # 张三print(age)    # 25

🎯 返回布尔值的函数

# 习惯:以 is/has/can 开头def is_even(n):    """判断是否偶数"""    return n % 2 == 0def has_vowel(text):    """判断是否包含元音"""    vowels = "aeiouAEIOU"    return any(c in vowels for c in text)def can_vote(age):    """判断是否可以投票"""    return age >= 18print(is_even(4))        # Trueprint(has_vowel("bcdf"))  # Falseprint(can_vote(20))       # True# 直接用在条件判断中if is_even(10):    print("是偶数")

🔄 函数作为参数

# 函数可以当参数传给另一个函数def apply(func, value):    return func(value)def double(x):    return x * 2def square(x):    return x ** 2print(apply(double, 5))   # 10print(apply(square, 5))   # 25

9. 实战练习

🎯 练习 1:温度转换工具

def celsius_to_fahrenheit(celsius):    """    摄氏度转华氏度    公式: F = C × 9/5 + 32    """    return celsius * 9 / 5 + 32def fahrenheit_to_celsius(fahrenheit):    """    华氏度转摄氏度    公式: C = (F - 32) × 5/9    """    return (fahrenheit - 32) * 5 / 9def temperature_advice(celsius):    """根据温度给出穿衣建议"""    if celsius < 0:        return "🥶 极寒!穿羽绒服、戴帽子手套"    elif celsius < 10:        return "🧥 很冷!穿厚外套"    elif celsius < 20:        return "👔 凉爽!穿长袖"    elif celsius < 30:        return "👕 温暖!穿短袖"    else:        return "🥵 炎热!注意防晒多喝水"# 测试temps_c = [0, 15, 25, 37, -10]for c in temps_c:    f = celsius_to_fahrenheit(c)    advice = temperature_advice(c)    print(f"  {c:5.1f}°C = {f:5.1f}°F | {advice}")

🎯 练习 2:密码强度检查器

def check_password_strength(password):    """    检查密码强度    评分标准:    - 长度 >= 8: +1分    - 包含大写字母: +1分    - 包含小写字母: +1分    - 包含数字: +1分    - 包含特殊字符: +1分    返回: (分数, 等级, 详细信息)    """    score = 0    details = []    # 检查长度    if len(password) >= 8:        score += 1        details.append("✅ 长度足够")    else:        details.append("❌ 长度不足8位")    # 检查大写字母    if any(c.isupper() for c in password):        score += 1        details.append("✅ 包含大写字母")    else:        details.append("❌ 缺少大写字母")    # 检查小写字母    if any(c.islower() for c in password):        score += 1        details.append("✅ 包含小写字母")    else:        details.append("❌ 缺少小写字母")    # 检查数字    if any(c.isdigit() for c in password):        score += 1        details.append("✅ 包含数字")    else:        details.append("❌ 缺少数字")    # 检查特殊字符    special = "!@#$%^&*()_+-=[]{}|;:',.<>?"    if any(c in special for c in password):        score += 1        details.append("✅ 包含特殊字符")    else:        details.append("❌ 缺少特殊字符")    # 评级    levels = {0: "极弱", 1: "弱", 2: "一般", 3: "中等", 4: "强", 5: "极强"}    level = levels[score]    return score, level, details# 测试passwords = ["123456", "abcdef", "Abc12345", "MyP@ss2024!"]for pwd in passwords:    score, level, details = check_password_strength(pwd)    stars = "⭐" * score    print(f"\n密码: {pwd}")    print(f"  评分: {score}/5 {stars}")    print(f"  等级: {level}")    for d in details:        print(f"  {d}")

🎯 练习 3:数学工具箱

def factorial(n):    """计算阶乘 n!"""    if n < 0:        return None    result = 1    for i in range(1, n + 1):        result *= i    return resultdef fibonacci(n):    """生成前 n 个斐波那契数"""    if n <= 0:        return []    if n == 1:        return [0]    fib = [0, 1]    for i in range(2, n):        fib.append(fib[i-1] + fib[i-2])    return fibdef 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 Truedef primes_in_range(start, end):    """返回范围内的所有素数"""    return [n for n in range(start, end + 1) if is_prime(n)]# 测试print(f"5! = {factorial(5)}")                    # 120print(f"斐波那契前10个: {fibonacci(10)}")         # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]print(f"17是素数? {is_prime(17)}")                # Trueprint(f"1-50的素数: {primes_in_range(1, 50)}")    # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

10. 今日小结

知识点
核心内容
定义函数
def 函数名(参数):
 + 缩进函数体
位置参数
按顺序传入,数量必须匹配
默认值参数
def f(x, y=10)
,有默认值的放后面
关键字参数
f(name="张三", age=25)
,指名道姓不怕乱序
return
返回值给调用者;不写 return 返回 None
多返回值
return a, b
 → 返回元组,可解包
文档字符串
"""描述"""
,函数说明书
布尔函数
is_
/has_/can_ 开头

🧠 记忆口诀:def 定义函数名,括号里面放参数。位置参数按序传,默认参数放后边。return 给值别忘写,None 返回没有它。docstring 写说明,三个月后不抓瞎。

🔮 预告: Day 14 函数进阶 — *args/**kwargs、变量作用域(global/nonlocal)、lambda 匿名函数。从"会写函数"到"写好函数"的关键一步!

轻松时刻:

请在微信客户端打开

最新文章

随机文章