一文弄懂 Python 动态参数(收藏起来慢慢看)

360影视 动漫周边 2025-05-19 10:37 2

摘要:写函数时参数总是写死,遇到参数数量变化就抓瞎?比如想写个求和函数,既能算两个数相加,又能算十个八个数相加;或者写个用户信息函数,有的人需要传年龄,有的人需要传地址,参数老是不够用...... 别慌!Python 的动态参数就是来解决这些的!

[赞] 点赞、收藏、加关注,下次找我不迷路

写函数时参数总是写死,遇到参数数量变化就抓瞎?比如想写个求和函数,既能算两个数相加,又能算十个八个数相加;或者写个用户信息函数,有的人需要传年龄,有的人需要传地址,参数老是不够用...... 别慌!Python 的动态参数就是来解决这些的!

一、啥是动态参数?先搞懂这两个符号 (一)*args:专治「位置参数太多」

先看个简单例子:假设我们要写一个函数,能计算任意个数的和。如果按普通方法写,参数数量固定,比如:

那如果要算 3 个数相加,就得再写个add(a, b, c),算 10 个数就得写 10 个参数,这显然太麻烦了!这时候*args就派上用场了,它就像一个能装任意多个位置参数的「魔法口袋」,把多个参数打包成一个元组。

用法演示:

def add(*args): total = 0 for num in args: total += num return totalprint(add(1, 2)) # 3print(add(1, 2, 3, 4)) # 10print(add(1, 2, 3, 4, 5, 6, 7)) # 28

这里的*args其实就是arguments的缩写,代表任意数量的位置参数。调用函数时,不管传多少个参数,都会被args这个元组装起来,然后我们就可以用循环来处理啦。

(二)**kwargs:搞定「关键字参数多变」

再来看另一个场景:比如我们要写一个打印用户信息的函数,不同用户可能有不同的属性,比如有的人需要传name和age,有的人需要传name、address和phone。这时候**kwargs就闪亮登场了,它是一个能装任意多个关键字参数的「百宝盒」,把参数打包成一个字典。

用法演示:

def print_info(**kwargs): for key, value in kwargs.items: print(f"{key}: {value}")print_info(name="小明", age=18)# 输出:# name: 小明# age: 18print_info(name="小红", address="北京", phone=13800001111)# 输出:# name: 小红# address: 北京# phone: 13800001111

**kwargs是keyword arguments的缩写,调用函数时传入的关键字参数(比如name="小明")会被收集到kwargs这个字典里,键是参数名,值是对应的值。我们可以用字典的items方法来遍历输出。

(三)一句话总结:单星打包位置参数,双星打包关键字参数

为了方便记忆,咱们来个简单的口诀:

「单星 * args,位置参数全收下;双星**kwargs,关键字参数装回家」

二、*args 和 **kwargs 的核心区别:一张表让你秒懂

为了让大家更清楚两者的区别,咱们用表格来对比一下:

特性

*args

**kwargs

语法

单个星号 + 参数名(*args)

两个星号 + 参数名(**kwargs)

传递方式

接收位置参数(如:1, 2, 3)

接收关键字参数(如:a=1, b=2)

接收类型

元组(tuple)

字典(dict)

应用场景

参数数量不定的位置参数

参数名称不定的关键字参数

参数顺序

按位置传递,顺序重要

按关键字传递,顺序不重要

举个生活中的例子帮助理解:*args 就像去超市购物,把选好的商品(位置参数)一股脑扔进购物车(元组),结账时按放进的顺序处理;kwargs 就像点外卖,把想要的菜品(关键字参数,比如「宫保鸡丁 = 1 份」)写在订单里(字典),商家按订单名称准备,不管你先写哪个后写哪个。

三、动态参数原来还能这么用! (一)混合使用:固定参数 + 动态参数,灵活又可控

有时候我们的函数既有固定参数,又需要动态参数,这时候只要注意顺序就行:** 固定参数在前,*args 在中间,kwargs 在最后。比如写一个函数,需要先传一个必选的title,然后可以传任意多个位置参数(比如文章的关键词),最后可以传任意多个关键字参数(比如作者信息):

def write_article(title, *keywords, **author_info): print(f"文章标题:{title}") print(f"关键词:{keywords}") print(f"作者信息:{author_info}")write_article("Python动态参数", "Python", "函数", "参数", name="小李", experience=3)# 输出:# 文章标题:Python动态参数# 关键词:('Python', '函数', '参数')# 作者信息:{'name': '小李', 'experience': 3}

这里的顺序一定不能搞错哦,如果把 **kwargs 放在 * args 前面,就会报错,因为 Python 会把后面的位置参数当成关键字参数,这就乱套啦~

(二)解包操作:把打包的参数再拆开用

前面咱们说的是用 * args 和 **kwargs 来打包参数,其实它们还能反过来「解包」,把已有的列表、元组、字典拆成单个参数传给函数。

1. 解包列表 / 元组:用单个星号 *

比如有一个列表nums = [1, 2, 3, 4],想传给前面写的add函数:

nums = [1, 2, 3, 4]print(add(*nums)) # 10,相当于调用add(1, 2, 3, 4)

这里的*nums就是把列表解包成单个的位置参数,传给add函数里的 * args。

比如有一个字典info = {"name": "小张", "age": 20},想传给print_info函数:

info = {"name": "小张", "age": 20}print_info(**info) # 相当于调用print_info(name="小张", age=20)# 输出:# name: 小张# age: 20

解包操作的口诀:单星解包序列(列表 / 元组),双星解包字典,打包解包灵活换,函数调用更方便~

(三)动态参数在函数扩展中的妙用:让旧函数兼容新需求

def old_func(a, b): print(f"a={a}, b={b}")

现在需求变了,需要增加一个参数c,但又不想破坏原来的调用方式(比如原来有很多地方调用old_func(1, 2))。这时候可以用动态参数来改造函数,让它既能接收旧的参数,又能处理新的参数:

def new_func(a, b, *args, **kwargs): old_func(a, b) # 先处理原来的固定参数 if args: print(f"新增的位置参数:{args}") if kwargs: if 'c' in kwargs: print(f"新增的c参数:{kwargs['c']}") # 其他新增参数处理...# 旧调用方式不变new_func(1, 2) # 输出:a=1, b=2# 新调用方式可以传c参数new_func(1, 2, c=3) # 输出:a=1, b=2,新增的c参数:3

这样一来,旧代码不用改,新需求也能满足,动态参数简直就是函数升级的「桥梁」!

四、有些问题别搞错 (一)参数顺序别搞错:固定参数→*args→**kwargs

前面提到过,混合使用时顺序很重要,要是写成def func(**kwargs, *args),直接就会报错啦!记住口诀:「固定参数先站好,单星双星往后靠」,保证不会错~

(二)别把 * args 和 **kwargs 当「万能钥匙」,够用就行

虽然动态参数很强大,但也不能滥用。如果函数明确知道需要几个固定参数,就别用动态参数,不然会让代码可读性变差。比如add(a, b)就比add(*args)更清晰,除非真的需要处理任意数量的参数。

(三)解包时注意数据类型

解包列表 / 元组到args 没问题,但如果把字典解包到args,就会得到字典的键作为位置参数。比如:

def func(*args): print(args)data = {"a": 1, "b": 2}func(*data) # 输出:('a', 'b'),因为*data解包的是字典的键

如果想解包字典的值,需要用data.values,或者直接用 **kwargs 来解包字典:

func(**data) # 这会报错,因为func不接收关键字参数,所以要用能接收**kwargs的函数(四)给动态参数取个好名字:别只用 args 和 kwargs

虽然*args和**kwargs是约定俗成的名字,但在实际项目中,如果能根据参数含义取更有意义的名字,会让代码更易读。比如处理学生成绩时,可以用*scores,处理用户信息时用**user_info,这样一看就知道里面装的是什么数据。

最后给大家整理个思维导图梳理一下重点

来源:科技站长

相关推荐