Python函数基础教程:吃透参数类型与默认参数,新手也能写模块化代码

86 阅读6分钟

函数是Python编程的核心基石,掌握函数的定义、调用及参数使用,能让你的代码从「线性堆砌」升级为「模块化设计」。本文聚焦Python函数的核心知识点——参数类型与默认参数,用实战案例拆解用法,解决新手最易踩的参数传值坑。

一、先搞懂:函数的基本定义与调用

在学参数之前,先掌握函数的基础语法,这是理解参数的前提。

1. 函数定义的核心结构

Python用def关键字定义函数,最基础的格式如下:

def 函数名(参数列表):
    """函数文档字符串(可选,用于说明函数功能)"""
    函数体(核心逻辑)
    return 返回值(可选,无return则默认返回None

2. 最简示例:无参数函数

先从最简单的无参数函数入手,理解「定义-调用」的基本流程:

 定义一个打印问候语的无参数函数
def print_greeting():
    """打印简单的问候语"""
    print("你好,欢迎学习Python函数!")

 调用函数(必须调用才会执行函数体)
print_greeting()
 输出:你好,欢迎学习Python函数!

二、核心重点:函数的参数类型

参数是函数的「输入接口」,不同参数类型适配不同的传值场景,新手需重点掌握以下4类常用参数。

1. 位置参数(必选参数)

最基础的参数类型,调用时必须按「定义顺序」传值,数量不能多也不能少,是Python函数的默认参数类型。

用法示例:

 定义计算两数之和的函数,a和b是位置参数
def add_numbers(a, b):
    """计算两个数的和"""
    result = a + b
    return result

 调用:按位置传值(a=3,b=5)
total = add_numbers(3, 5)
print(total)   输出:8

 错误示例:少传参数(必选参数缺失)
 add_numbers(3)   报错:TypeError: add_numbers() missing 1 required positional argument: 'b'

新手避坑:

  • 位置参数的传值顺序必须和定义顺序一致,比如add_numbers(5, 3)会让a=5b=3
  • 调用时参数数量必须与定义完全匹配,多传或少传都会报错。

2. 关键字参数

调用函数时,通过「参数名=值」的形式传值,无需严格按位置顺序,适合参数较多的场景,能避免传值顺序混乱。

用法示例:

 定义包含多个参数的函数
def print_user_info(name, age, city):
    """打印用户信息"""
    print(f"姓名:{name},年龄:{age},城市:{city}")

 方式1:纯关键字参数(顺序可随意)
print_user_info(age=28, name="张三", city="北京")
 输出:姓名:张三,年龄:28,城市:北京

 方式2:位置参数+关键字参数(关键字参数必须在位置参数后)
print_user_info("李四", city="上海", age=30)
 输出:姓名:李四,年龄:30,城市:上海

 错误示例:关键字参数在前
 print_user_info(city="广州", "王五", 25)   报错:SyntaxError

3. 默认参数(重点)

给参数设置「默认值」,调用时可省略该参数(使用默认值),也可主动传值覆盖默认值,适合「大部分场景用固定值,少数场景需修改」的需求。

核心语法与示例:

 定义带默认参数的函数(city默认值为"深圳")
 注意:默认参数必须放在位置参数之后!
def print_student_info(name, grade, city="深圳"):
    """打印学生信息,城市默认为深圳"""
    print(f"姓名:{name},年级:{grade},城市:{city}")

 调用1:省略默认参数(使用默认值"深圳")
print_student_info("小明", 3)
 输出:姓名:小明,年级:3,城市:深圳

 调用2:覆盖默认参数(传值"杭州")
print_student_info("小红", 4, "杭州")
 输出:姓名:小红,年级:4,城市:杭州

 调用3:用关键字参数覆盖默认值(更清晰)
print_student_info("小刚", 5, city="成都")
 输出:姓名:小刚,年级:5,城市:成都

默认参数的关键注意事项(新手必看):

  1. 默认参数的位置:必须放在所有位置参数之后,否则会报语法错误。 错误示例:def func(city="北京", name): ...(默认参数在前,报错)
  2. 默认参数的赋值时机:默认参数的值在「函数定义时」确定,而非调用时,避免使用可变对象(如列表、字典)作为默认参数。 反面示例(踩坑):
     错误示范:用列表作为默认参数
    def add_item(item, lst=[]):
        lst.append(item)
        return lst
    
    print(add_item(1))   输出:[1]
    print(add_item(2))   输出:[1, 2](而非预期的[2])
    
    正确写法(用None作为占位符):
    def add_item(item, lst=None):
        if lst is None:
            lst = []
        lst.append(item)
        return lst
    
    print(add_item(1))   输出:[1]
    print(add_item(2))   输出:[2]
    

4. 可变长度参数(拓展)

若不确定需要接收多少个参数,可用*args(接收任意数量位置参数)或**kwargs(接收任意数量关键字参数),补充学习能应对更灵活的场景。

示例:

 *args:接收多个位置参数(打包成元组)
def sum_all(*args):
    """计算任意多个数的和"""
    total = 0
    for num in args:
        total += num
    return total

print(sum_all(1, 2, 3))   输出:6
print(sum_all(5, 10, 15, 20))   输出:50

 **kwargs:接收多个关键字参数(打包成字典)
def print_details(**kwargs):
    """打印任意关键字参数"""
    for key, value in kwargs.items():
        print(f"{key}{value}")

print_details(subject="数学", score=95, teacher="李老师")
 输出:
 subject:数学
 score:95
 teacher:李老师

三、实战案例:用默认参数写实用函数

结合默认参数和位置参数,封装一个「计算商品折扣价」的函数,加深理解:

def calculate_discount(price, discount=0.1):
    """
    计算商品折扣价
    :param price: 商品原价(必选参数)
    :param discount: 折扣率,默认0.1(即9折)
    :return: 折扣后的价格
    """
    final_price = price * (1 - discount)
     保留2位小数,符合金额格式
    return round(final_price, 2)

 场景1:使用默认折扣(9折)
price1 = calculate_discount(100)
print(f"原价100元,9折后:{price1}元")   输出:原价100元,9折后:90.0元

 场景2:自定义折扣(8折)
price2 = calculate_discount(200, 0.2)
print(f"原价200元,8折后:{price2}元")   输出:原价200元,8折后:160.0元

 场景3:用关键字参数传折扣(更清晰)
price3 = calculate_discount(150, discount=0.05)
print(f"原价150元,95折后:{price3}元")   输出:原价150元,95折后:142.5

四、常见错误与解决方法

错误现象根本原因解决方法
TypeError: func() missing 1 required positional argument: 'x'必选参数未传值检查调用时的参数数量,补充缺失的位置参数
SyntaxError: non-default argument follows default argument默认参数放在了位置参数前面调整参数顺序,默认参数必须在所有位置参数之后
默认参数使用列表/字典时,多次调用结果叠加可变对象作为默认参数,定义时初始化一次用None作为默认值,在函数内部重新初始化可变对象
TypeError: func() got multiple values for argument 'x'同一参数既按位置传值,又按关键字传值避免重复传值,比如func(1, x=2)会触发该错误