函数的基本使用

Python 函数全套完整笔记(定义、调用、返回值、参数详解)

一、函数基础概念

1.1 函数是什么?

函数其实就是一种组织代码、封装功能的方式。

程序类比理解:

  • 函数 → 具备某一独立功能的工具

  • 定义函数 → 事先制作、准备好工具

  • 调用函数 → 遇到对应场景,直接拿来使用工具

1.2 为什么要使用函数?

在没有函数封装功能之前,想要重复使用某一段功能代码,只能反复复制粘贴,会产生严重问题:

  1. 代码冗余:大量重复代码,程序结构混乱、可读性极差

  2. 维护性、扩展性差:功能需要修改时,所有重复代码都要逐一修改,极易出错

1.3 函数使用原则与分类

1.3.1 核心原则

先定义、后调用,必须遵守,顺序颠倒程序报错。

1.3.2 函数两大分类

  1. 内置函数:Python 官方提前定义好的函数,可直接调用(如 print、input、len 等)

  2. 自定义函数:开发者根据业务需求,自己定义的功能函数

二、函数的定义

2.1 函数定义语法(标准完整版)

# 完整定义格式
def 函数名(参数1,参数2,参数3,...):
    """
    函数功能描述
    :param 参数1: 参数1大致介绍
    :param 参数2: 参数2大致介绍
    :param 参数3: 参数3大致介绍
    :return: 介绍一下函数的返回值
    """
    代码1
    代码2
    代码3
    return 值

2.1.1 示例:简易登录函数

def login():
    username = input("请输入您的用户名:").strip()
    password = input("请输入您的用户名:").strip()
    if username == "egon" and password == "123":
        print('登录成功')
    else:
        print('登录失败')

2.2 定义函数的底层逻辑与特性

定义函数与定义普通变量本质逻辑一致,都是绑定内存地址:

x = 10
print(x)    # 打印普通变量名,输出变量值
print(login)  # 打印函数名,输出函数的内存地址

核心特性:定义函数阶段,只检测语法,不执行函数体代码。

即使函数体内代码语法错误,只要定义阶段语法无误,不会报错,调用时才会触发报错。

# 定义时不报错,调用才会报错
def func():
    if 1==1
        print("ok")

2.3 函数定义的三种形式

2.3.1 无参函数

定义函数时,括号内无任何参数,适用于固定功能、无需传入数据的场景。

def say_hello():
    print("="*50)
    print('welcome to home page')
    print("="*50)

say_hello()

2.3.2 有参函数

定义函数时,括号内指定形参,调用时必须传入对应实参,根据传入数据实现动态功能。

# 两数求和函数
def my_sum(x,y):
    print(x + y)

my_sum(1,2)

# 带参数登录函数
def login(username, password):
    if username == "egon" and password == "123":
        print('登录成功')
    else:
        print('登录失败')

login("egon","aaa")

2.3.3 空函数

函数体使用 pass 占位,无实际代码逻辑,用于项目架构搭建、先定义功能占位,后续补充逻辑。

def register():
    """注册功能"""
    pass

def login():
    """登录功能"""
    pass

def withdraw():
    """取款功能"""
    pass

三、函数的调用

3.1 调用语法

语法:函数名(),加括号即可触发函数内部代码执行

login()
login()
login()

报错提醒:只有函数可以加括号调用,普通变量、None 值均不能调用

# 错误写法
x = 10
x()

x = None
x()

3.2 调用函数的执行逻辑

调用函数时,程序会跳转执行函数体内部所有代码,执行完毕后回到调用位置继续执行后续代码。

3.2.1 嵌套调用练习1

def bar():
    print('from bar')

def foo():
    print('from foo')
    bar()

foo()

3.2.2 嵌套调用练习2(先定义后调用,无顺序问题)

def foo():
    print('from foo')
    bar()

def bar():
    print('from bar')

foo()

3.2.3 嵌套调用练习3(报错案例)

# 报错:调用foo时,bar还未定义
def foo():
    print('from foo')
    bar()

foo()

def bar():
    print('from bar')

四、函数返回值 return

4.1 return 核心特性

  1. return 是函数结束的唯一标志:函数内可写多个 return,只要执行任意一个,函数立即终止,后续代码不再执行

  2. return 会将后面的值,作为本次函数调用的结果返回

def foo():
    print("hello")
    return 1
    print("world")
    return 2
    print("egon")
    return 3

foo()

4.1.1 示例:返回两数最大值

def foo(x, y):
    if x > y:
        return x
    else:
        return y

res = foo(3, 5)
print(res * 12)

4.2 return 返回值规则

  1. 函数无 return、或 return 后无值,默认返回 None

  2. return 后跟单个值,直接返回该值本身(任意数据类型)

  3. return 后跟多个值(逗号分隔),会自动封装为元组返回

def foo():
    print('hello')
    print('xx')
    print('yyy')
    return 111, "aaa", [333, 444]

res = foo()
print(res)

4.3 函数调用的三种格式

def foo(x, y):
    if x > y:
        return x
    else:
        return y

4.3.1 语句形式:仅执行功能,不接收返回值

foo(1, 2)

4.3.2 表达式形式:接收返回值并二次运算

res = foo(1,2) * 10

4.3.3 函数调用作为另一个函数的参数

res = foo(foo(5,9),11)
print(res)

五、函数参数核心详解(形参、实参)

5.1 参数基础定义

  1. 形参:定义函数时括号内的参数,本质是变量名

  2. 实参:调用函数时括号内传入的值,本质是变量值

  3. 绑定关系:调用函数时,实参值绑定形参;函数执行结束,绑定解除,资源回收

def foo(x,y):
    # x = 1
    # y = 2
    pass

foo(1,2)

5.2 位置参数

5.2.1 位置形参

定义函数时,从左到右依次定义的形参,必须传值,缺一不可、多一不行。

def foo(x, y, z):
    print(x, y, z)

# 正常传参
foo(111,222,333)
# 报错:参数过多
# foo(111,222,333,444)
# 报错:参数缺失
# foo(111,222)

5.2.2 位置实参

调用函数时,按从左到右的位置顺序传值,位置一一对应,顺序错误则赋值错误。

foo(111,222,333)
foo(333,111,222)

5.3 关键字参数(实参)

调用函数时,以 key=value 形式指名赋值,无需遵循位置顺序。

5.3.1 核心注意事项

  1. 位置实参与关键字实参可以混用,但位置实参必须在前,关键字实参在后

  2. 同一个形参不能重复赋值

def foo(x, y, z):
    print(x, y, z)

# 正确混用
foo(111, 666, z=333, y=222)
# 纯关键字传参
foo(z=333,y=222,x=111)
# 正确写法
foo("egon", gender='male', age=18)
# 错误写法:位置参数在后
# register(name="egon",18,gender='male')

5.4 默认参数(形参)

定义函数时,提前为形参赋值,调用函数时可省略该参数,自动使用默认值。

5.4.1 三大注意点

  1. 默认形参必须放在位置形参后方

  2. 默认参数仅在函数定义阶段赋值一次,存储的是内存地址

  3. 默认参数建议使用不可变类型,避免可变类型带来的逻辑隐患

5.4.2 示例1:基础默认参数

def register(name, age, gender='male'):
    print(name, age, gender)

register('egon', 18)
register('tom', 19)
register('jack', 38)
register('lili', 19, 'female')

5.4.3 示例2:默认参数定义阶段赋值特性

m = 10
def foo(x, y=m):
    print(x, y)

foo(1)

5.4.4 示例3:可变类型默认参数隐患

m = [111,222,333]
def foo(x, y=m):
    print(x, y)

foo(1)
m.append(666)
foo(1)

5.4.5 示例4:默认参数最优写法(规避可变类型隐患)

def register(name, hobby, hobbies=None):
    if hobbies is None:
        hobbies = []
    hobbies.append(hobby)
    print('%s 爱好是 %s' % (name, hobbies))

register('egon', 'basketball')
register('tom', 'read')
register('jack', 'music')
register('lili','sleep',['xxx','yyy'])

5.5 可变长参数 * 与 **

适用场景:调用函数时传入的实参个数不固定、溢出,用于接收多余实参。

溢出实参分为两种:溢出位置实参、溢出关键字实参,对应两种可变参数。

5.5.1 *args 接收溢出位置实参

将所有溢出的位置实参打包成元组,赋值给 args。

def foo(x,y,*z):
    print(x,y,z)

foo(1,2,3,4,5)

# 累加器案例
def foo(*nums):
    res = 0
    for i in nums:
        res += i
    print(res)

foo(1, 2, 3, 4, 5)
foo(1, 2)

5.5.2 **kwargs 接收溢出关键字实参

将所有溢出的关键字实参打包成字典,赋值给 kwargs。

def foo(x, y, **z):
    print(x, y)
    print(z)

foo(1, 2, a=1, b=2, c=3)

5.5.3 * 在实参中的用法(打散序列)

* 可遍历序列(列表、字符串、元组、字典键),将序列打散为位置实参传入函数。

def foo(x, y, z):
    print(x, y, z)

foo(1, *[222, 333])   # 等价 foo(1,222,333)
foo(1, *"he")         # 等价 foo(1,"h","e")
foo(1, *"hello")      # 等价 foo(1,"h","e","l","l","o")
foo(1, *{"k1":111,"k2":333}) # 仅打散键:foo(1,"k1","k2")

5.5.4 ** 在实参中的用法(打散字典)

** 仅可后跟字典,将字典打散为关键字实参传入函数。

def foo(x, y, z):
    print(x, y, z)

foo(111, **{"z": 333, "y": 222})  # 等价 foo(111,y=222,z=333)
# 报错:多余关键字参数
# foo(111, **{"z": 333, "y": 222, "aaa": 333})

5.5.5 通用参数组合:*args、**kwargs

行业通用写法:*args 接收任意位置参数,**kwargs 接收任意关键字参数,适配所有传参场景。

def wrapper(*args, **kwargs):
    print(args, kwargs)
    index(*args, **kwargs)

5.6 命名关键字参数

定义在 *args 之后、**kwargs 之前的参数,必须以关键字形式传参,可设置默认值。

5.6.1 核心特点

  1. 无默认值的命名关键字参数,调用时必须手动传值

  2. 传值方式固定:只能用 key=value 关键字传参

def foo(x, y=111, *args, m=666, n, **kwargs):
    print("x:", x)
    print("y:", y)
    print("args: ", args)
    print("m: ", m)
    print("n:", n)
    print("kwargs: ", kwargs)

# 完整传参调用
foo(1,222,333,444,555,m=6666666,n=777,a=1,b=2,c=3)
# 报错:缺失必填命名关键字参数 n
# foo(1,222,333,444,555,a=1,b=2,c=3)
posted @ 2026-07-08 19:25  cuckooyang  阅读(16)  评论(0)    收藏  举报