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_wlist_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.7065 ,它们是元组 ('绮梦',1.70,65) 的各个元素。
    • 然后使用 person = item[0]height = item[1]weight = item[2] 去访问这些元素的元素,这是错误的,因为 item 已经是元组的元素,而不是包含姓名、身高、体重的列表或元组。
    • 对于字符串 '绮梦' 来说,它没有 [1][2] 索引,对于数字 1.7065 来说,它们也没有 [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_wlist_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中创建和调用函数,以及如何通过不同的方式传递参数和从函数中返回值。掌握这些基础知识,将帮助你编写更加模块化和可重用的代码。

posted @ 2024-12-26 16:45  Linux运维技术栈  阅读(6)  评论(0编辑  收藏  举报