Python函数(十二):函数的创建和调用、参数传递、返回值
前言:在编程的世界里,函数是一种基本的构建块,它允许我们将代码封装成可重复使用的单元。在Python中,函数的使用尤为重要,因为它不仅有助于代码的模块化,还提高了代码的可读性和可维护性。本章节,我们将深入探讨Python函数的创建和调用、参数传递以及返回值这三个核心概念。
函数的创建和调用:
函数的创建,也就是定义一个函数,涉及到指定函数名、定义参数以及编写函数体。这个过程就像是在告诉Python,“嘿,当有人叫我的时候,按照这些步骤来执行”。函数的调用则是触发这个预定义行为的过程,它允许我们利用函数封装的代码来执行特定的任务。
参数传递:
参数传递是函数使用中的一个关键特性,它允许我们将数据传递给函数。这些数据,也就是参数,可以是数字、字符串、列表,甚至是其他函数。通过参数传递,我们可以定制函数的行为,使其能够处理不同的输入,从而更加灵活和强大。
返回值:
返回值是函数执行完毕后提供的结果。通过返回值,函数可以将处理后的数据传递回给调用者。这不仅使得函数可以执行计算和数据处理的任务,还可以作为程序流程控制的一部分,根据返回值来决定后续的操作。
在接下来的内容中,我们将通过具体的代码示例来详细解释这些概念,并展示如何在实际编程中应用它们。通过学习这些基础知识,你将能够更好地理解和使用Python函数,从而编写出更加高效和优雅的代码。让我们开始吧!
一、函数的创建和调用
函数是执行特定任务的代码块。在Python中,我们使用def
关键字来定义一个函数。
1、创建函数
理解函数的基本概念:
- 函数是一段可重用的代码,用于执行特定任务。
- 函数可以带有参数,这些参数是函数执行时需要的输入。
- 函数可以返回值,这是函数执行后的结果。
定义一个函数的基本语法如下:
def function_name(parameters):
# 函数体
function_name
是你为函数选择的名字。parameters
是函数的参数,用于接收传递给函数的数据。
注意:即使参数没有参数,也必须保留一对空的“()”,否则语法不对会报错。
2、调用函数
一旦函数被定义,你可以通过函数名后跟括号来调用它,如果函数需要参数,则在括号内传递相应的参数。
function_name(arguments)
function_name
函数名称,要调用的函数名称必须是已经创建好的。arguments
可选参数,用于指定各个参数的值。如果需要传递多个参数值,则各参数值间使用逗号,
分隔。
示例:
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # 输出: Hello, Alice!
实例训练46 -输出每日一贴(共享版)
def function_tips():
'''功能:每天输出一条励志文字
'''
import datetime
#定义一个列表
mot = ["今天星期一: \n坚持下去不是因为我很坚强,而是因为我别无选择",
"今天星期二: \n含泪播种的人一定能笑着收获",
"今天星期三: \n做对的事情比把事情做对重要",
"今天星期四: \n命运给予我们的不是失望之酒,而是希望之杯",
"今天星期五: \n不要等到明天,明天太遥远,今天就行动",
"今天星期六: \n求知若饥,虚心若愚",
"今天星期日: \n成功将属于那些从不说”不可能“的人"]
day = datetime.datetime.now().weekday() #获取当前日期
print(mot[day]) #输出每日一贴
#***************************调用函数***************************#
function_tips()
二、参数传递
参数传递是函数使用中的一个重要概念,它允许函数接收外部数据。
1、形式参数与实际参数
- 形式参数:在定义函数时,函数后面括号中的参数为“形式参数”。
- 实际参数:在调用一个参数时,函数名后面括号中的参数为“实际参数”,也就是将函数的调用者提供给函数的参数为实际参数。
示例:
#定义函数
def demo(obj):
print("原值: ",obj)
obj += obj
# 调用函数
print("=========値传递========")
mot = "唯有在被追赶的时候,你才能真正地奔跑。"
print("函数调用前: ",mot)
demo(mot) #采用不可变对象————字符串
print("函数调用后: ",mot)
print("=========引|用传递========")
list1 = ['绮梦','冷伊一','香凝','黛兰']
print("函数调用前: ",list1)
demo(list1) #采用可变对象--列表
print("函数调用后: ",list1)
实例训练47 -根据身高、体重计算BMI指数(共享版)
def fun_bmi(person, height, weight):
'''功能:根据身高和体重计算BMI指数
person:姓名
height:身高,单位:米
weight:体重,单位:千克
'''
print(person + "的身高: " + str(height) + "米 \t 体重: " + str(weight) + "千克")
bmi = weight / (height * height) # 用于计算BMI指数,公式为:BMI=体重/身高的平方
print(person + "的BMI指数为: " + str(bmi)) # 输出BMI指数
# 判断身材是否合理
if bmi < 18.5:
print("您的体重过轻 ~@_@~\n")
elif bmi >= 18.5 and bmi < 24.9:
print("正常范围,注意保持 (-_-)\n")
elif bmi >= 24.9 and bmi < 29.9:
print("您的体重过重 ~@ @~\n")
elif bmi >= 29.9:
print("肥胖 ^@_@^\n")
# *************************调用函数************************* #
fun_bmi("路人甲", 1.83, 60) # 计算路人甲的BMI指数
fun_bmi("路人乙", 1.60, 50) # 计算路人乙的BMI指数
2、位置参数
位置参数依赖于参数的顺序。调用函数时,实际参数的位置必须与定义函数时的形式参数顺序相匹配。
① 数量必须与定义时一致
在调用函数时,指定的实际参数的数量必须与形式参数的数量一致,否则会报错。如:
② 位置必须与定义时一致
在调用函数时,指定的实际参数的位置必须与形式参数的位置一致,否则会报错。如:
示例:
def add(a, b):
return a + b
result = add(5, 3) # result 为 8
3、关键字参数
关键字参数通过参数名传递,提高了代码的可读性。
示例:
def greet(name, job):
print(f"Hello, {name}. You are a {job}.")
greet(name="Alice", job="Engineer") # 输出: Hello, Alice. You are a Engineer.
4、为参数设置默认值
调用函数时,如果没有指定某个参数将抛出异常。为了解决这个问题,我们可以为参数设置默认值,即在定义函数时,直接指定形式参数的默认值。这样,当没有传入参数时,则直接使用定义函数时设置的默认值。定义带有默认值参数的函数语法格式如下:
def functionname(...,[parameter1 = defaultvalue1]):
[functionbody]
functionname
:函数名称,在调用函数时使用。parameter1 = defaultvalue1
:可选参数,用于指定向函数中传递的参数,并且为该参数设置默认值为defaultvalue1。functionbody
:可选参数,用于指定函数体,即函数被调用后,要执行的功能代码。
示例:
def fun_bmi(height, weight, person = "路人"):
'''功能:根据身高和体重计算BMI指数
person:姓名
height:身高,单位:米
weight:体重,单位:千克
'''
print(person + "的身高: " + str(height) + "米 \t 体重: " + str(weight) + "千克")
bmi = weight / (height * height) # 用于计算BMI指数,公式为:BMI=体重/身高的平方
print(person + "的BMI指数为: " + str(bmi)) # 输出BMI指数
# 判断身材是否合理
if bmi < 18.5:
print("您的体重过轻 ~@_@~\n")
elif bmi >= 18.5 and bmi < 24.9:
print("正常范围,注意保持 (-_-)\n")
elif bmi >= 24.9 and bmi < 29.9:
print("您的体重过重 ~@ @~\n")
elif bmi >= 29.9:
print("肥胖 ^@_@^\n")
fun_bmi(1.73,62)
延申知识点①:
在Python中,每个函数对象都有一个 __defaults__
属性,它是一个元组,包含了函数定义时给出的默认值参数。这个属性可以用来查看函数的默认参数值。对于您的 fun_bmi
函数,您可以使用以下代码来查看默认值:
print(fun_bmi.__defaults__)
这将输出:
('路人',) # 表示person参数的默认值为"路人"
延申知识点②:
如果使用可变对象作为函数参数的默认值时,多次调用可能会导致意料之外的情况:
def demo(obj=[]):
print("obj的值: ",obj)
obj.append(1)
demo()
demo()
以下是对这段 Python 代码的详细解释:
函数定义:
def demo(obj=[]):
print("obj的值: ", obj)
obj.append(1)
def demo(obj=[])
:定义了一个名为demo
的函数,它有一个参数obj
,这个参数的默认值是一个空列表[]
。在 Python 中,当使用默认参数时,如果该参数是可变对象(例如列表、字典、集合等),并且在函数内部对该参数进行了修改操作,会产生一些意想不到的结果,因为默认参数在函数定义时就已经创建,并且在后续的函数调用中会持续使用这个创建好的对象,而不是每次调用函数时重新创建。print("obj的值: ", obj)
:在函数内部,首先打印出obj
的当前值。obj.append(1)
:对obj
列表进行修改操作,向列表中添加元素1
。
函数调用:
demo()
- 第一次调用
demo()
函数:- 由于没有传递参数,使用
obj
的默认值,也就是一个空列表。 - 首先打印
obj
的值,此时obj
的值是[]
。 - 然后执行
obj.append(1)
,将元素1
添加到obj
列表中,此时obj
列表变为[1]
。
- 由于没有传递参数,使用
demo()
- 第二次调用
demo()
函数:- 仍然没有传递参数,使用
obj
的默认值。但是,由于默认参数obj
在函数定义时就已经创建了一个列表,而且这个列表在第一次调用时已经被修改为[1]
,所以这个列表不会重新初始化为空列表。 - 首先打印
obj
的值,此时obj
的值是[1]
(因为第一次调用时添加了元素1
)。 - 然后执行
obj.append(1)
,将元素1
再次添加到obj
列表中,此时obj
列表变为[1, 1]
。
- 仍然没有传递参数,使用
总结:
这段代码的主要问题在于使用了可变对象作为函数的默认参数。在 Python 中,函数的默认参数在函数定义时只创建一次,而不是每次调用函数时都创建。所以,如果使用可变对象作为默认参数,并且在函数内部修改了这个对象,那么后续调用函数时,该对象会保留之前修改的状态。如果想要避免这种情况,可以这样修改函数:
def demo(obj=None):
if obj is None:
obj = []
print("obj的值: ", obj)
obj.append(1)
demo(obj=None)
demo(obj=None)
这样,每次调用函数时,如果没有传递参数,都会重新创建一个新的空列表作为 obj
的值,而不会受到之前调用的影响。
总之,在使用函数的默认参数时,对于可变对象要格外小心,避免因为默认参数的特性而导致函数的行为不符合预期。
5、可变参数
- *args:允许你传递任意数量的位置参数。
- **kwargs:允许你传递任意数量的关键字参数。
在Python中,可变参数允许函数接受任意数量的参数。这包括两种类型:*args
(用于接收任意数量的位置参数)和**kwargs
(用于接收任意数量的关键字参数)。下面我将分别解释这两种可变参数的使用和区别。
① *args
:接收任意数量的位置参数
*args
允许你将一个不定数量的位置参数传递给函数,这些参数在函数内部被存储在一个元组中。使用 *args
时,你可以在函数定义中包含其他位置参数,但 *args
必须放在所有位置参数的后面。
示例:
def example(*args):
for arg in args:
print(arg)
example(1, 2, 3) # 输出:1 2 3
example('a', 'b', 'c') # 输出:a b c
在这个例子中,example
函数可以接受任意数量的位置参数,并将它们打印出来。
实例训练48 -根据身高、体重计算BMI指数(共享升级版)
def fun_bmi_upgrade(*person):
'''功能:根据身高和体重计算BMI指数
*person:可变参数,该参数中需要传递3个元素的列表。
分别为姓名、身高(单位:米)和体重(单位:千克)
'''
for list_person in person:
for item in list_person:
person = item[0] # 姓名
height = item[1] # 身高(单位:米)
weight = item[2] # 体重(单位:千克)
print("\n" + "="*13,person,"="*13)
print("身高: " + str(height) + "米 \t 体重: " + str(weight) + "千克")
bmi = weight / (height * height) # 用于计算BMI指数,公式为:BMI=体重/身高的平方
print("的BMI指数为: " + str(bmi)) # 输出BMI指数
# 判断身材是否合理
if bmi < 18.5:
print("您的体重过轻 ~@_@~\n")
elif bmi >= 18.5 and bmi < 24.9:
print("正常范围,注意保持 (-_-)\n")
elif bmi >= 24.9 and bmi < 29.9:
print("您的体重过重 ~@ @~\n")
elif bmi >= 29.9:
print("肥胖 ^@_@^\n")
# *************************调用函数************************* #
list_w = [('绮梦',1.70,65),('零语',1.78,50),('黛兰',1.72,66)]
list_m = [('悻轩',1.80,75),('冷少',1.75,70)]
fun_bmi_upgrade(list_w ,list_m) # 调用函数指定可变参数
注意事项
写到这里其实可以发现有个问题就是for里嵌套了个内循环,这一点是可以优化的:
以上代码将内循环一段除掉了改成:
for list_person in person:
name = list_person[0] # 姓名
height = list_person[1] # 身高(单位:米)
weight = list_person[2] # 体重(单位:千克)
语法纠正:
修改原因:
-
原代码中的内循环
for item in list_person:
是多余的。当调用函数fun_bmi_upgrade(list_w, list_m)
时,list_w
和list_m
是列表,其中的元素是元组,例如list_w = [('绮梦',1.70,65),('零语',1.78,50),('黛兰',1.72,66)]
。在for list_person in person:
循环中,list_person
会遍历这些元组,例如('绮梦',1.70,65)
。如果不修改,使用原代码的内循环for item in list_person:
会导致以下问题:item
会依次为'绮梦'
、1.70
、65
,它们是元组('绮梦',1.70,65)
的各个元素。- 然后使用
person = item[0]
、height = item[1]
和weight = item[2]
去访问这些元素的元素,这是错误的,因为item
已经是元组的元素,而不是包含姓名、身高、体重的列表或元组。 - 对于字符串
'绮梦'
来说,它没有[1]
或[2]
索引,对于数字1.70
或65
来说,它们也没有[0]
、[1]
、[2]
索引,会导致IndexError
或逻辑错误。
-
修改为
name = list_person[0]
、height = list_person[1]
和weight = list_person[2]
的原因:list_person
本身就是存储个人信息的元组,例如('绮梦',1.70,65)
。list_person[0]
可以直接提取出姓名,list_person[1]
可以直接提取出身高,list_person[2]
可以直接提取出体重。这样的代码更简洁,逻辑更清晰,避免了多余的循环和错误的索引访问。- 这种方式准确地从存储人员信息的元组中提取出所需的信息,符合函数的预期输入,即
*person
是包含三个元素(姓名、身高、体重)的列表或元组,并且在后续的计算和判断中能够正确使用这些信息。
代码解释:
def fun_bmi_upgrade(*person):
:定义了一个名为fun_bmi_upgrade
的函数,使用*person
作为可变参数,可以接收多个参数,这些参数会被存储在person
元组中。for list_person in person:
:遍历person
元组,其中list_person
是存储个人信息的元组,如('绮梦',1.70,65)
。name = list_person[0]
:从元组中提取姓名。height = list_person[1]
:从元组中提取身高。weight = list_person[2]
:从元组中提取体重。bmi = weight / (height * height)
:根据公式计算 BMI 指数。- 一系列
if-elif
语句:根据计算得到的 BMI 指数判断体重状态并输出相应信息。
调用部分:
list_w
和list_m
是存储人员信息的列表,每个元素是一个元组,包含姓名、身高和体重。fun_bmi_upgrade(list_w, list_m)
:调用函数并将存储人员信息的列表作为参数传入。
通过这种修改,代码能够更清晰地提取元组中的信息,避免了多余的循环和潜在的错误,使代码更简洁、准确地完成计算 BMI 指数和给出体重状态判断的功能。
② **kwargs
:接收任意数量的关键字参数
**kwargs
允许你将一个不定数量的关键字参数传递给函数,这些参数在函数内部被存储在一个字典中。使用 **kwargs
时,你可以在函数定义中包含其他关键字参数,但 **kwargs
必须放在所有关键字参数的后面。
示例:
def example(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
example(name="Alice", age=25) # 输出:name: Alice age: 25
example(country="Wonderland", book="Alice's Adventures in Wonderland") # 输出:country: Wonderland book: Alice's Adventures in Wonderland
在这个例子中,example
函数可以接受任意数量的关键字参数,并将它们打印出来。
以下是一个使用生辰八字作为示例,结合 **kwargs
语法的 Python 代码:
def analyze_birth_chart(**kwargs):
"""
此函数接收任意数量的关键字参数,其中关键字为生辰八字的部分,值为相应的信息
函数将打印出每个生辰八字部分及其相关信息
"""
for part, info in kwargs.items():
print(f"生辰八字部分: {part}")
print(f"信息: {info}\n")
# 调用函数并传递不同生辰八字部分的信息
analyze_birth_chart(
年柱="代表祖先和幼年时期,对人一生的根基和起点有重要影响,其五行属性影响一个人的基本性格和命运走势。",
月柱="反映一个人的青年时期运势,与家庭、父母的关系密切,其地支所藏人元会影响人的情绪和气质。",
日柱="代表自己和中年时期,是生辰八字的核心,决定了一个人的主要性格和命运特征,被称为日主。",
时柱="体现一个人的晚年运势,与子女后代有关,也会影响一个人最终的归宿和晚年生活状态。"
)
代码解释:
def analyze_birth_chart(**kwargs):
:定义了一个名为analyze_birth_chart
的函数,使用**kwargs
作为参数,允许接收任意数量的关键字参数。for part, info in kwargs.items():
:使用kwargs.items()
方法获取kwargs
字典中的键值对。part
存储关键字(生辰八字部分),info
存储相应的值(信息)。print(f"生辰八字部分: {part}")
和print(f"信息: {info}\n")
:使用f-string
格式化字符串将生辰八字部分及其信息打印出来,并添加一个换行符以提高可读性。
调用部分:
- 在调用
analyze_birth_chart
函数时,我们传递了多个关键字参数,每个关键字是生辰八字的一部分,相应的值是该部分的描述。这些关键字参数将被自动存储在kwargs
字典中。
使用场景
*args
:当你需要传递一个不确定数量的位置参数时,比如在函数需要接受多个值但具体数量未知的情况下。**kwargs
:当你需要传递一个不确定数量的命名参数时,比如在函数需要接受多个命名参数但具体哪些参数未知的情况下。
注意事项
*args
和**kwargs
只能出现在函数参数列表的最后。- 你可以在同一个函数中同时使用
*args
和**kwargs
,但*args
必须在**kwargs
之前。 - 使用
*args
和**kwargs
可以让你的函数更加灵活,但过度使用可能会导致代码难以理解和维护。
通过使用这些可变参数,你可以编写出更加通用和灵活的函数,以适应不同的调用场景。
三、返回值
函数可以通过return
语句返回一个值给调用者。如果函数没有return
语句,则默认返回None
。格式:
return [value]
参数说明:value
可选参数,用于指定要返回的值,可以返回一个值,也可以返回多个值。
示例:
def add_numbers(a, b):
return a + b
result = add_numbers(3, 4) # result 现在是 7
实例训练49 -模拟结账功能-计算实付金额
def fun_checkout(money):
'''功能:计算商品合计金额并进行折扣处理
money:保存商品金额的列表
返回商品的合计金额和折扣后的金额
'''
money_old = sum(money) #计算合计金额
money_new = money_old
if 500 <= money_old < 1000: #满500可享受9折优惠
money_new = '{:.2f}'.format(money_old * 0.9)
elif 1000 <= money_old <= 2000: #满1000可享受8折优惠
money_new = '{:.2f}'.format(money_old * 0.8)
elif 2000 <= money_old <= 3000: #满2000可享受7折优惠
money_new = '{:.2f}'.format(money_old * 0.7)
elif money_old >= 3000: #满3000可享受7折优惠
money_new = '{:.2f}'.format(money_old * 0.6)
return money_old, money_new #返回总金额和折扣后的金额
# **********************调用函数********************** #
print("\n开始结算......\n")
list_money = [] #定义保存商品金额的列表
while True:
# 请不要输入非法的金额,否则将抛出异常
inmoney = float(input("输入商品金额 (输入0表示输入完毕): "))
if int(inmoney) == 0:
break #退出循环
else:
list_money.append(inmoney) #将金额添加到金额列表中
money = fun_checkout(list_money) #调用函数
print("合计金额: ",money[0], "应付金额: ", money[1]) #显示应付金额
总结
通过本文,我们了解了如何在Python中创建和调用函数,以及如何通过不同的方式传递参数和从函数中返回值。掌握这些基础知识,将帮助你编写更加模块化和可重用的代码。