当前位置: 代码网 > it编程>前端脚本>Python > Python 函数、参数与返回值实例详解

Python 函数、参数与返回值实例详解

2026年09月17日 Python 我要评论
相信大家看了前几章python教程,能明显发现,这些代码基本上都是从上往下执行的。前面那些案例,我主要是用来模拟演示的,在实际的项目开发过程中,这种写法既低效又繁琐,尤其是在需要重复执行同一套逻辑时,

相信大家看了前几章python教程,能明显发现,这些代码基本上都是从上往下执行的。前面那些案例,我主要是用来模拟演示的,在实际的项目开发过程中,这种写法既低效又繁琐,尤其是在需要重复执行同一套逻辑时,更是显而易见。

举个例子,leader让你开发商品折扣的计算功能,如果反复遇到同样的计算逻辑,你就得把每一个计算公式都写一遍。这么做一方面,效率低下,另一方面,如果你后期想修改折扣规则的时候,容易漏改某一处。但如果你把这套逻辑写成函数,以后遇到同样的业务场景,就可以直接调用函数。那我们今天这一章,要讲解的内容,就是函数的定义和调用,以及参数与返回值的常见写法,下面我们开始吧。

一、为什么要使用函数

先看一段没有使用函数的代码:

price1 = 200
final_price1 = price1 * 0.8
print(final_price1)
price2 = 350
final_price2 = price2 * 0.8
print(final_price2)

两次计算使用的是同一套规则,只是商品价格不同。可以把计算过程放进一个函数:

def calculate_discount(price):
    final_price = price * 0.8
    return final_price
print(calculate_discount(200))
print(calculate_discount(350))

这样写以后,折扣规则只保留一份。如果折扣从八折改成九折,只需要修改函数里面的计算。

函数还有一个作用,就是给一段逻辑起名字。看到 calculate_discount(),基本就能知道这段代码在计算折扣,不需要每次都重新阅读里面的细节。

二、定义和调用函数

python 使用 def 定义函数:

def say_hello():
    print("hello")

这一段代码由几个部分组成:

def 函数名():
    函数体
  • def 表示开始定义一个函数。
  • say_hello 是函数名。
  • 函数名后面要写一对圆括号 ()
  • 行尾的冒号 : 不能省略。
  • 函数体需要缩进。

定义函数并不会立即执行函数体。需要使用函数名加圆括号进行调用:

say_hello()

完整代码是:

def say_hello():
    print("hello")
say_hello()
say_hello()

函数调用了两次,因此会打印两次 hello

三、函数的执行过程

程序执行到函数定义时,会记住这个函数,不过不会进入函数体。执行到函数调用时,才会进入函数内部:

def show_message():
    print("正在执行函数")
print("调用之前")
show_message()
print("调用之后")

输出顺序为:

调用之前
正在执行函数
调用之后

调用结束以后,程序会回到原来的位置,继续执行函数调用后面的代码。

函数通常要先定义,再调用。下面的代码会出现 nameerror

say_hello()
def say_hello():
    print("hello")

python 从上到下执行。调用 say_hello() 时,后面的函数定义还没有执行,所以此时找不到这个名字。

四、参数和实参

函数如果只能执行一套固定内容,用途会比较有限。参数可以让调用者把不同的数据传入函数:

def greet(name):
    print(f"hello,{name}")
greet("ivan")
greet("tom")

定义函数时,圆括号中的 name 叫作形参。调用函数时传入的 "ivan""tom" 叫作实参。

可以简单理解为,形参是函数内部准备接收数据的变量,实参是调用时真正交给函数的数据:

def greet(name):       # name 是形参
    print(name)
greet("ivan")         # "ivan" 是实参

很多时候大家也会把它们都称为参数,只要知道它们分别出现在定义和调用阶段即可。

五、多个参数

函数可以接收多个参数,参数之间使用逗号分隔:

def add(a, b):
    result = a + b
    print(result)
add(10, 20)

调用时传入的实参数量要与形参数量对应。下面少传了一个参数,会出现 typeerror

add(10)

多传参数同样会报错:

add(10, 20, 30)

除非函数使用了后面要讲的不定长参数,否则参数数量不能随意增加或减少。

六、位置参数

按照参数在函数定义中的位置传值,叫作位置参数:

def introduce(name, age, city):
    print(f"姓名:{name}")
    print(f"年龄:{age}")
    print(f"城市:{city}")
introduce("ivan", 20, "杭州")

调用时,第一个实参交给 name,第二个交给 age,第三个交给 city

位置写错以后,python 不一定会报错,但是数据的含义可能已经变了:

introduce(20, "杭州", "ivan")

这段代码可以运行,不过 name 得到的是 20age 得到的是 "杭州"。所以使用位置参数时,需要记住参数顺序。

七、关键字参数

调用函数时,也可以明确写出参数名:

introduce(name="ivan", age=20, city="杭州")

这种写法叫作关键字参数。因为参数名称已经写清楚,所以顺序可以调整:

introduce(city="杭州", name="ivan", age=20)

关键字参数更长一些,不过参数较多,或者某个布尔值、数字的含义不明显时,会更容易读懂:

def create_video(width, height, fps, muted):
    print(width, height, fps, muted)
create_video(width=1920, height=1080, fps=30, muted=true)

如果只写成 create_video(1920, 1080, 30, true),最后的 true 代表什么就不太直观。

位置参数和关键字参数可以一起使用,但是位置参数必须写在关键字参数前面:

introduce("ivan", age=20, city="杭州")

下面的写法会出现语法错误:

introduce(name="ivan", 20, "杭州")

八、默认参数

有些参数在大多数时候使用同一个值,可以在定义函数时设置默认值:

def greet(name, message="hello"):
    print(f"{message},{name}")
greet("ivan")
greet("tom", "早上好")

第一次调用没有传入 message,所以使用默认值 "hello"。第二次传入了新的内容,默认值会被覆盖。

必填参数要放在默认参数前面:

def greet(name, message="hello"):
    print(message, name)

下面的顺序不正确:

def greet(message="hello", name):
    print(message, name)

因为调用时无法确定只传入一个位置参数时,它应该交给谁,python 会直接提示语法错误。

默认参数适合处理真正具有常用默认值的设置,例如页码、排序方式和是否显示某个选项:

def search(keyword, page=1, page_size=20):
    print(keyword, page, page_size)
search("python")
search("python", page=2)

九、不要使用可变对象作为默认值

默认参数还有一个很容易踩到的问题。下面的写法看起来像是每次调用都创建一个空列表:

def add_item(item, items=[]):
    items.append(item)
    return items
print(add_item("python"))
print(add_item("java"))

实际结果为:

['python']
['python', 'java']

默认值是在函数定义时创建的,不是每次调用时重新创建。同一个列表会被后续调用继续使用。

通常改成 none,再在函数内部创建新列表:

def add_item(item, items=none):
    if items is none:
        items = []
    items.append(item)
    return items

字典和集合也是可变对象,不建议直接作为默认参数。字符串、数字、布尔值、none 这类不可变值通常没有这个问题。

十、使用*args接收多个位置参数

如果函数需要接收的参数数量不固定,可以在参数名前加一个星号 *

def calculate_total(*prices):
    total = 0
    for price in prices:
        total += price
    return total
print(calculate_total(20, 35, 18))
print(calculate_total(10, 20, 30, 40, 50))

这里的 prices 是一个元组。调用时传入多少个位置参数,它就保存多少个:

def show_args(*args):
    print(args)
    print(type(args))
show_args(1, 2, 3)

输出结果为:

(1, 2, 3)
<class 'tuple'>

args 只是常用名称,真正让它接收多个参数的是前面的 *。不过实际编写代码时通常还是沿用 args,这样别人一眼就能看懂。

普通参数可以和 *args 一起出现:

def print_scores(title, *scores):
    print(title)
    for score in scores:
        print(score)
print_scores("第一次考试", 86, 92, 78)

第一个实参交给 title,剩余的位置参数都放入 scores

十一、使用**kwargs接收多个关键字参数

两个星号 ** 可以接收数量不固定的关键字参数:

def create_user(**info):
    print(info)
create_user(name="ivan", age=20, city="杭州")

这里的 info 是一个字典:

{'name': 'ivan', 'age': 20, 'city': '杭州'}

调用时写下的参数名会成为字典的键,传入的数据会成为对应的值。

kwargs 同样只是常用名称,真正起作用的是 **

def show_info(**kwargs):
    for key, value in kwargs.items():
        print(key, value)

*args 保存额外的位置参数,得到元组;**kwargs 保存额外的关键字参数,得到字典。

十二、不同参数的排列顺序

普通参数、默认参数、*args**kwargs 可以放在同一个函数中:

def show_data(name, age=18, *args, **kwargs):
    print("name:", name)
    print("age:", age)
    print("args:", args)
    print("kwargs:", kwargs)
show_data(
    "ivan",
    20,
    "python",
    "java",
    city="杭州",
    active=true,
)

结果为:

name: ivan
age: 20
args: ('python', 'java')
kwargs: {'city': '杭州', 'active': true}

基础阶段可以先记住常用顺序:普通参数、带默认值的参数、*args**kwargs

参数写得太多以后,调用和维护都会变得麻烦。如果一组数据本身属于同一个对象,例如用户信息,很多时候直接传入一个字典会更合适,没有必要为了展示参数写法把函数设计得特别复杂。

十三、使用return返回结果

前面的部分函数直接使用 print() 输出结果,但是输出和返回并不是一回事:

def add(a, b):
    print(a + b)

这个函数会把结果打印到终端,不过调用者拿不到计算结果继续使用。改成 return

def add(a, b):
    return a + b
result = add(10, 20)
print(result)

return 会把结果交回函数调用的位置,所以可以把它保存到变量中,也可以参与后续计算:

total = add(10, 20) * 2
print(total)

打印适合把信息显示出来,返回值适合让程序继续使用结果。实际函数中经常需要返回数据,不应该为了看到结果就把所有内容都写成 print()

十四、return会结束函数

程序执行到 return 以后,会立即离开函数,后面的代码不会再执行:

def check_age(age):
    if age < 0:
        return "年龄不能小于 0"
    return "年龄有效"
print(check_age(-1))
print(check_age(20))

这种写法经常用来提前处理不符合要求的数据:

def divide(a, b):
    if b == 0:
        return none
    return a / b

b 等于 0 时,函数返回 none 并结束,不会继续执行除法。

下面的第二个 print() 永远不会执行:

def test():
    return 100
    print("这一行不会执行")

十五、函数没有写return会怎样

如果函数没有写 return,或者只写了一个没有返回值的 return,python 会默认返回 none

def show_message():
    print("hello")
result = show_message()
print(result)

输出结果为:

hello
none

这也是为什么一个只负责打印内容的函数,把调用结果保存到变量以后会得到 none

下面两种写法的返回结果相同:

def func1():
    pass
def func2():
    return

它们都会返回 none

十六、返回多个值

一个函数可以在 return 后面写多个值:

def calculate(a, b):
    total = a + b
    difference = a - b
    return total, difference
result = calculate(10, 3)
print(result)

输出结果为:

(13, 7)

看起来像是返回了两个独立的值,其实 python 会把它们放进一个元组。

调用时可以直接解包:

total, difference = calculate(10, 3)
print(total)
print(difference)

左侧变量的数量要与返回值数量对应,否则会出现 valueerror

如果返回内容比较多,而且每项都有明确含义,使用字典往往更清楚:

def analyze_scores(scores):
    return {
        "count": len(scores),
        "max": max(scores),
        "min": min(scores),
        "average": sum(scores) / len(scores),
    }

十七、参数传递的是对象

调用函数时,形参会引用传入的对象。对于数字、字符串和元组这类不可变对象,函数内部重新赋值不会修改外面的变量:

def change_number(number):
    number = 100
value = 10
change_number(value)
print(value)

结果仍然是 10

列表、字典和集合是可变对象。如果函数直接修改对象中的内容,外部也能看到变化:

def add_skill(skills):
    skills.append("python")
user_skills = ["java"]
add_skill(user_skills)
print(user_skills)

输出结果为:

['java', 'python']

如果不希望修改原列表,可以在函数内部创建副本并返回:

def add_skill(skills):
    new_skills = skills.copy()
    new_skills.append("python")
    return new_skills

这一部分和前面学过的可变对象有关。更完整的对象引用、浅拷贝和深拷贝会在后面的章节中单独讲。

十八、函数文档字符串

函数的第一行可以写一段文档字符串,用来说明函数做什么、接收什么参数以及返回什么内容:

def calculate_discount(price, rate=0.8):
    """根据原价和折扣率计算折后价格。"""
    return price * rate

文档字符串使用三引号,通常放在函数体的第一行。可以通过 help() 查看:

help(calculate_discount)

简单函数的说明不需要写得很长,不过函数要提供给别人使用,或者参数含义不够直观时,文档字符串会比较有用。

十九、函数命名

函数名通常使用小写字母和下划线,尽量表达它实际完成的操作:

def calculate_total():
    pass
def get_user_info():
    pass
def save_file():
    pass

f1()do_it() 这类名字虽然可以运行,但是很难从调用位置判断函数的用途。

函数应该尽量完成一件相对明确的事情。一个函数里同时读取文件、处理数据、连接数据库、发送消息,后面修改和测试都会比较麻烦。不过也没有必要把每一两行代码都拆成函数,还是要看这段逻辑是否会重复使用,以及单独命名以后是不是更清楚。

二十、综合示例:计算订单价格

下面写一个订单价格函数。它接收商品价格列表、折扣率和运费,返回订单的各项金额:

def calculate_order(prices, discount=1.0, shipping_fee=0):
    """计算订单原价、折扣金额和最终价格。"""
    if not prices:
        return {
            "subtotal": 0,
            "discount_amount": 0,
            "shipping_fee": shipping_fee,
            "final_price": shipping_fee,
        }
    subtotal = sum(prices)
    discounted_price = subtotal * discount
    discount_amount = subtotal - discounted_price
    final_price = discounted_price + shipping_fee
    return {
        "subtotal": subtotal,
        "discount_amount": discount_amount,
        "shipping_fee": shipping_fee,
        "final_price": final_price,
    }
order = calculate_order(
    prices=[99, 128, 56],
    discount=0.9,
    shipping_fee=10,
)
print("商品原价:", order["subtotal"])
print("优惠金额:", order["discount_amount"])
print("运费:", order["shipping_fee"])
print("最终价格:", order["final_price"])

这里把 prices 作为必填参数,因为没有商品价格就无法正常计算。discountshipping_fee 有常用默认值,所以设置成默认参数。

函数返回字典,而不是直接打印结果。这样调用者可以决定如何使用数据,可以打印到终端,也可以显示在页面上或者继续参与其他计算。

空列表会走前面的 return,直接返回一份金额为零的结果,后面的计算不会继续执行。

二十一、常见错误

1. 定义函数以后忘记调用

def say_hello():
    print("hello")

这里只完成了定义。如果希望它执行,还要写 say_hello()

2. 调用函数时忘记圆括号

result = say_hello

这行代码取得的是函数本身,没有调用函数。调用要写成 say_hello()

3. 参数数量不一致

def add(a, b):
    return a + b
add(10)

函数需要两个参数,只传入一个会出现 typeerror

4. 把print()当成返回值

def add(a, b):
    print(a + b)
result = add(10, 20)
print(result)

函数打印了 30,但是没有返回结果,因此 resultnone

5. 在return后面继续写要执行的代码

return 会立即结束函数。确实需要执行的内容,应该放在 return 前面。

6. 使用列表作为默认参数

可变默认值会被多次调用共同使用。需要空列表时,通常把默认值写成 none,再在函数内部创建列表。

二十二、练习

练习一:计算矩形面积

编写一个函数,接收矩形的长度和宽度,返回矩形面积。

练习二:判断奇偶数

编写一个函数,接收一个整数。偶数返回 true,奇数返回 false

练习三:计算平均分

使用 *args 接收数量不固定的成绩,返回平均分。没有传入成绩时返回 none

练习四:创建用户信息

使用 **kwargs 接收用户姓名、年龄和城市,返回一个用户信息字典。

练习五:订单价格

在综合示例的基础上增加满减规则,例如订单原价达到 300 时再减 20,并把满减金额放进返回结果。

函数可以把一段会重复使用的逻辑单独保存起来,参数负责把数据传入函数,return 负责把处理结果交回调用位置。下一章我们就来讲变量作用域、匿名函数和高阶函数。

以上就是python 函数、参数与返回值实例详解的详细内容,更多关于python 函数、参数与返回值的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com