Python *args 用法笔记

整理自《Effective Python 编写高质量 Python 代码的 59 个有效方法》第 18 条。

1. 定义、用法

在 def 语句中使用 *args,即可令函数接受数量可变的位置参数。

比如确定一个函数接收 message 信息参数和 values 值参数,但不确定 values 有几个值,解决方法可以把 values 定义成列表,有数据就塞入列表,无数据就空列表,得到如下函数代码:

def log(message,values):
    if not values:
        print(message)
    else:
        value_str = ", ".join(str(x) for x in values)
        print(f"{message}: {value_str}")


log("My numbers are",[1,2])
log("Hi",[])

倘若不想使用列表,就想直接将 values 值一个个作为参数传入函数,可以在最后的位置参数前加 * 表示可以跟随任意数量的位置参数:

def log(message,*values):
    if not values:
        print(message)
    else:
        value_str = ", ".join(str(x) for x in values)
        print(f"{message}: {value_str}")


log("My numbers are",1,2)
log("Hi")

此时就不需要将 values 做成列表来传入了,有数据就传,没数据就空着。

2. * 操作符分解序列

此外,我采用了刚 *values 的位置参数标注法,但我现在拿到的是个列表,想把列表中的元素作为参数传上去,这个要怎么处理,总不能再重写个函数吧?这里就要用到在列表前加星号了,看代码,函数定义不变,但调用函数传参数时给列表前加个星号:

def log(message,*values):
    if not values:
        print(message)
    else:
        value_str = ", ".join(str(x) for x in values)
        print(f"{message}: {value_str}")


log("My numbers are",1,2)
log("Hi")
# 看这里
log("My numbers are",*[1,2,3,4,5])

这种 *[1,2,3,4,5] 的形式就是对列表拆解,将其中元素拿出来当参数使用

3. 可能耗尽内存并崩溃

变长参数传给函数时,总是要先转化成元组。那么当我们把刚刚 *[1,2,3,4,5] 要拆解的列表换成个生成器,把它当参数传入函数时,Python 就必须把该生成器完整迭代一轮将所有生成的值放入元组,这就有可能消耗大量内存并导致程序崩溃。

使用 *args 来表示任意参数主要是为了简化程序员编码工作,并使代码更加易读。

4. 可能产生难以排查的 bug

对于已经使用 *args 位置参数的函数,如果以后要给函数添加新的位置参数,那就必须修改原来调用该函数的旧代码。若只在参数列表前添加新的位置参数,而不更新现有的调用代码,则可能会产生难以调试的错误。

例如我们在刚刚代码基础上添加个 sequence 参数:

def log(sequence,message,*values):
    if not values:
        print(message)
    else:
        value_str = ", ".join(str(x) for x in values)
        print(f"{sequence}:{message}: {value_str}")


# 正常
log(1,"My numbers are",1,2)
# 错误,但不报错
log("My numbers are",7,33)

添加了新参数、但仍按之前某种方式调用时,参数混乱配置,但没抛出异常仍是正常运行。

为了彻底避免此类情况,我们应该使用只能以关键字形式指定的参数(keyword-only argument) 来扩展这种接受 *args 的函数。

  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值