专栏首页Python空间有趣的 Python 特性 3 | 当心「默认可变参数」这个大猪蹄子。

有趣的 Python 特性 3 | 当心「默认可变参数」这个大猪蹄子。

本文字数:1575 字 阅读本文大概需要:4 分钟

写在之前

Python 提供了很多让使用者觉得舒服至极的功能特性,但是随着不断的深入学习和使用 Python,我发现其中存在着许多玄学的输出与之前预想的结果大相径庭,这个对于初学者来说难以理解,但是在理解它们以后又会觉得是这么的有意思,所以我准备了这个「有趣的 Python 特性」系列,写一些我碰到或看到的一些你所不知道的「奇葩」,这里面会涉及到在 Python2 和 Python3 中的异同,希望大家能从学习的过程中体会到真正的乐趣。

当心默认可变参数

首先我们先来看一个例子:

def test_func(default_arg=[]):
    default_arg.append('rocky0429')
    return default_arg

我们都知道如果调用上述函数 1 次以后所出现的结果:

>>> test_func()
['rocky0429']

那么如果调用 2 次,3 次呢?你可以先自己思考一下再继续看下面的结果:

>>> test_func()
['rocky0429', 'rocky0429']
>>> test_func()
['rocky0429', 'rocky0429', 'rocky0429']

咦?明明我们的函数里明明对默认的可变参数赋值了,为什么第 1 次调用是初始化的状态,第 2 次,第 3 次出现的结果就不是我们想要的了呢?先别急,我们再继续看下面的调用:

>>> test_func([])
['rocky0429']
>>> test_func()
['rocky0429', 'rocky0429', 'rocky0429', 'rocky0429']

是不是更懵了?

其实出现这样的结果是因为 Python 中函数的默认可变参数并不是每次调用该函数时都会初始化。相反,它们会使用最近分配的值作为默认值。在上述的 test_func([]) 的结果不同是因为,当我们将明确的 [] 作为参数传递给 test_func() 的时候,就不会使用 test_func 的默认值,所以函数返回的是我们期望的值。

在自定义函数的特殊属性中,有个「 __defaults__」 会以元组的形式返回函数的默认参数。下面我们就用「 __defaults__」来演示一下,以便让大家有个更直观的感觉:

>>> test_func.__defaults__ #还未调用
([],)
>>> test_func() # 第 1 次
['rocky0429']
>>> test_func.__defaults__ # 第 2 次的默认值
(['rocky0429'],)
>>> test_func() # 第 2 次
['rocky0429', 'rocky0429']
>>> test_func.__defaults__ # 第 2 次的默认值
(['rocky0429', 'rocky0429'],)
>>> test_func([]) # 输入确定的 []
['rocky0429']
>>> test_func.__defaults__ # 此时的默认值
(['rocky0429', 'rocky0429'],)

那么上面那种情况该如何避免呢?毕竟我们还是希望在每次调用函数的时候都是初始化的状态的?这个也很简单,就是将 None 指定为参数的默认值,然后检查是否有值传给对应的参数。所以对于文章开始的那个例子,我们可以改成如下的形式:

def test_func(default_arg=None):
    if not default_arg:
        default_arg = []
    default_arg.append('rocky0429')
    return default_arg

以上,完美解决。

本文分享自微信公众号 - Python空间(Devtogether),作者:Rocky0429

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python 中那些令人防不胜防的坑(二)

    人不能两次踏入同一条河流,在无数次踩进同样的坑里之后,我觉得我有必要整理一下,这是 Python 防坑系列第二篇。

    Rocky0429
  • 有趣的 Python 特性 1 | 是谁吃掉了我的外部变量?

    Python 提供了很多让使用者觉得舒服至极的功能特性,但是随着不断的深入学习和使用 Python,我发现其中存在着许多玄学的输出与之前预想的结果大相径庭,这个...

    Rocky0429
  • 无所遁形!我们搜集了1000多条辟谣信息,总结出疫情谣言四大套路

    2020年的农历新年,不仅考验着年轻人宅家自救的定力,还考验着他们如何晓之以情、动之以理劝亲人们戴上口罩的本领。

    Rocky0429
  • 【犀牛鸟学问】CCF YOCSEF“社交网络与大数据前沿”学术报告会诚邀您的参与

    犀牛鸟学问特别活动 犀牛鸟学问特别活动CCF YOCSEF“社交网络与大数据前沿” 学术报告会将于6月22日周四下午在腾讯北京分公司希格玛大厦举行。 本次报告会...

    腾讯高校合作
  • SpringMVC返回图片的几种方式

    SpringMVC返回图片的几种方式 后端提供服务,通常返回的json串,但是某些场景下可能需要直接返回二进制流,如一个图片编辑接口,希望直接将图片流返回给前...

    小灰灰
  • 社交网络斋戒实验报告

    ? 腾讯研究院S-Tech研究团队        报告下载:社交斋戒报告节选   1研究综述 1.1研究缘起 过去十余年,我们经历了一场传统社交的革...

    腾讯研究院
  • SpringMVC返回图片的几种方式

    主要借助的是 HttpServletResponse这个对象,实现case如下

    小灰灰
  • 答同学问(三)

    Git课程因为有些事耽搁了,会尽快更新。今天先来说几个之前有人问过的关于Python的几个小问题。 1. 如何查看异常处理时except里的出错信息? 给ex...

    Crossin先生
  • 工程实践中的体系与系统

    原文链接:https://mp.weixin.qq.com/s/36JDczJu8CmmiaLU1IhCpg

    月牙寂道长
  • EOS刚上线,我们研究了189个基于EOS的DAPP ……

    北京时间2018年6月15日凌晨1点,全网15%EOS持有者完成投票,EOS主网正式上线!但这仅仅是开始。EOS生态是否能够可持续发展——DAPP的丰富性是其关...

    互链脉搏

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动