【从0-1学习Python | 第六篇】 Python 函数:定义、参数与返回值

前言

函数可以把一段逻辑封装起来,调用时传入参数,执行后再通过返回值交回结果。理解函数的定义、参数和返回值后,再看不定长参数、函数作为参数以及订单金额计算,就能看清函数如何处理和传递数据。

一、定义函数并调用

使用 def 定义函数,函数名后面的小括号用于声明参数,缩进代码是函数体。定义函数时,函数体不会立即执行;只有调用函数时,里面的代码才会运行。

python 复制代码
def one():
    print("hello")

print("a")
one()

程序先输出 a,再调用 one(),输出 hello。调用时写函数名和括号,即使函数不需要参数,也不能省略括号。

函数可以接收参数,让同一段逻辑处理不同的数据。下面的函数接收半径 r,计算圆的面积并返回结果:

python 复制代码
def circle(r):
    area = 3.14 * r ** 2
    return area

a = circle(10)
print(a)

调用 circle(10) 时,参数 10 传给 r,函数计算出面积后通过 return 返回;调用结果被赋给变量 a。按这段代码的计算,输出为 314.0。

二、函数参数:把数据传进去

调用函数时,参数可以按位置传入,也可以通过参数名传入:

python 复制代码
circle(10)     # 位置传参
circle(r=10)   # 关键字传参

位置传参按照函数定义中的参数顺序匹配;关键字传参直接指定参数名,可读性更清楚。传入的参数需要和函数定义相匹配。

当需要接收的参数数量不固定时,可以使用 *args 和 **kwargs。*args 会把多余的位置参数收集为元组,**kwargs 会把关键字参数收集为字典:

python 复制代码
def calc_data(*args, **kwargs):
    min_data = min(args)
    max_data = max(args)
    avg_data = sum(args) / len(args)

    if kwargs.get("round") is not None:
        avg_data = round(avg_data, kwargs.get("round"))

    if kwargs.get("print"):
        print(min_data, max_data, avg_data)

    return min_data, max_data, avg_data

data = calc_data(100, 200, 300, 400, round=2, print=True)
print(data)

调用时,100、200、300、400 被收集到 args 中;round=2 和 print=True 被收集到 kwargs 中。函数用 args 计算最小值、最大值和平均值,再根据可选配置决定是否保留小数位、是否打印结果。

这里要注意,args 为空时,min(args) 和 max(args) 无法计算,因此这个函数要求调用方至少传入一个数值。

*args 和 **kwargs 也适合区分必需数据与可选配置。奶茶示例中,奶茶名称是核心数据,甜度、冰度和加料是定制选项:

python 复制代码
def order_milk_tea(*args, **kwargs):
    # 核心数据:奶茶名称(必点,数量不确定,可以点多杯)
    print(f"点的奶茶:{args}")

    # 选项:甜度、冰度、加料、大小等配置参数
    if kwargs:
        print(f"定制选项:")
        for key, value in kwargs.items():
            print(f"  {key}:{value}")
    else:
        print("  无定制选项,按默认制作 ~")

    print("-" * 30)

# 场景1:只要一杯奶茶,不定制选项
order_milk_tea("珍珠奶茶")

# 场景2:点奶茶 + 定制各种选项
order_milk_tea("珍珠奶茶", 甜度="少糖", 冰度="去冰", 加料=["布丁", "珍珠"], 大小="大杯")

# 场景3:多杯奶茶 + 部分选项
order_milk_tea("珍珠奶茶", "烤奶", "杨枝甘露", 甜度="无糖", 大小="中杯")

第一种调用只传入奶茶名称,kwargs 为空;后两种调用还传入了定制选项。这个写法适用于核心数据数量不固定、同时允许调用方指定额外配置的场景。

三、函数返回值:把结果传出来

return 把函数计算出的结果交回调用处。函数可以返回一个值,也可以在 return 后用逗号分隔多个值:

python 复制代码
def cirle2(r):
    """
    返回多个值
    :param r:
    :return:
    """
    return round(3.14 * r ** 2, 1), round(2 * 3.14 * r, 1)

area, circumference = cirle2(10)
print(area)
print(circumference)

这里返回的是圆的面积和周长。Python 会把多个返回值组合成一个元组,因此也可以先用一个变量接收,再查看它的类型:

python 复制代码
result = cirle2(10)
print(result)
print(type(result))

如果返回结果确定有多个,也可以像前面的示例一样用多个变量解包。使用有含义的变量名,例如 circumference,比使用 len 这类内置函数名更清楚,也能避免覆盖内置名称。

如果函数执行到末尾都没有遇到 return,调用结果会是 None。

四、函数中的变量与 global

函数内部赋值的变量通常属于函数内部。要在函数中给全局变量重新赋值,需要用 global 声明:

python 复制代码
num = 100

def circle(a):
    global num
    num = 88
    return a * num

b = circle(5)
print(num)

调用 circle(5) 后,num 被改成 88,因此最后输出 88。global num 让函数中的赋值作用于全局变量。由于这种修改会影响函数外部的状态,读代码时需要留意函数是否改变了全局变量。

五、把函数作为参数传递

函数名可以作为参数传给另一个函数。接收函数的代码可以调用它,从而把具体操作交给调用方决定:

python 复制代码
def add(a, b):
    return a + b

def sub(a, b):
    return a - b

def mul(a, b, oper):
    return oper(a, b)

result = mul(10, 20, add)
print(result)

调用时把 add 传给参数 oper,mul 内部执行 oper(a, b),所以结果为 30。这个例子中,mul 的实际行为由传入的函数决定;传入 sub 时就会执行减法。

简单的函数也可以用 lambda 表达式定义。冒号左侧是参数,右侧是一个表达式:

python 复制代码
outline = lambda: print("------------")
outline()

add = lambda a, b: a + b
print(add(1, 2))

lambda 适合表达简单、单行的操作。例如,按字符串长度对列表进行降序排序:

python 复制代码
data_list = ["C++", "C", "Python", "PHP", "Java", "Go"]
data_list.sort(key=lambda item: len(item), reverse=True)
print(data_list)

key 接收用于比较的规则,这里针对每个字符串计算长度;reverse=True 表示按长度从大到小排序。sort() 会直接修改原列表。

六、综合示例:计算订单金额

订单函数通过 *args 接收多件商品,通过关键字参数接收优惠券、积分和运费。每件商品使用一个元组表示,依次包含商品名、单价和数量:

python 复制代码
def cal_order_cost(*args, coupon, score, express):
    """
    根据传入的一批商品信息(商品名,价格,数量),优惠(优惠券,积分抵扣),运费信息计算订单的总金额
    :param args: 商品信息(商品名,价格,数量) --->如:("鼠标",188,2)
    :param coupon:
    :param score:
    :param express:
    :return:
    """
    #1.计算商品总金额
    total_price = [goods[1] * goods[2] for goods in args]
    total_cost = sum(total_price)

    #2.扣减优惠券
    if total_cost >= 5000 and coupon <= total_cost:
        total_cost -= coupon

    if total_cost >= 5000 and score // 100 <= total_cost:
        total_cost -= score // 100

    # 4.添加运费
    total_cost += express
    return total_cost

total = cal_order_cost(
    ("鼠标", 188, 2),
    ("键盘", 388, 1),
    ("手机", 3999, 1),
    coupon=10,
    score=4000,
    express=9.9
)
print(total)

由于 coupon、score 和 express 声明在 *args 后面,它们需要通过关键字传入。函数用商品元组的第二项乘以第三项得到每件商品的小计,再将小计求和。

示例中的商品总额是 188 × 2 + 388 × 1 + 3999 × 1 = 4763,低于 5000,因此优惠券和积分抵扣条件都不成立;加上 9.9 运费后,结果为 4772.9。运行脚本得到的输出也是 4772.9。

需要留意积分门槛的判断顺序:代码先扣除优惠券,再检查 total_cost >= 5000。如果商品原价满 5000,但优惠券扣减后低于 5000,当前代码就不会抵扣积分;这与注释中"商品总金额满 5000"的描述不完全一致。score // 100 表示积分按整百换算,例如 4050 积分按 40 元计算。

七、类型注解

类型注解可以标明变量、参数和返回值预期使用的类型,便于读代码和使用类型检查工具:

python 复制代码
a2: int = 444
names: list[str | int] = ["A", "B", 1, 2]

liststr \| int 表示列表元素可以是字符串或整数。这种注解表达预期类型,但不会自动转换值,也不会在所有情况下阻止类型不匹配;str | int 这种联合类型写法需要 Python 3.10 或更高版本。

函数的类型注解也可以标在参数和返回值上,例如将商品信息标为包含名称、价格和数量的元组,并在函数签名中标明其他参数与返回值的类型。类型注解用于说明约定,不会代替运行时校验。

函数的核心是明确输入和输出:参数说明数据从哪里来,函数体负责处理,返回值把结果交回调用处。设计函数时,先区分必需数据与可选配置,再检查返回值是否能准确表达处理结果。

相关推荐
燕落南枝1 小时前
HTML 学习:input 单选、复选与文件域详解
服务器·学习·html
G018_star sky♬1 小时前
java中的字符串常见方法
java·开发语言
熊猫钓鱼>_>1 小时前
Kotlin Multiplatform for OpenHarmony 实战:kotlinx-serialization JSON 适配
开发语言·华为·kotlin·华为云·json·harmonyos·code
MasonYyp2 小时前
声音转文字的模型
python
银河技术2 小时前
从脚本到 Operator:用 Go 构建可靠的微服务自动扩缩容控制器
开发语言·微服务·golang
GIS数据转换器4 小时前
地下空间综合管廊运营管理平台
大数据·开发语言·人工智能·经验分享·perl
Wang's Blog9 小时前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
信誓旦旦的程序猿10 小时前
【Python量化实战宝典 #08】可转债与债券接口手册:转股价·溢价率·纯债价值(Python 可跑)
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
砚底藏山河10 小时前
python量化:行情数据回溯
java·开发语言·python·金融·maven