我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python函数的默认参数请勿定义可变类型详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python函数的默认参数请勿定义可变类型详解

函数的默认参数请勿定义可变类型

经常会看到这样一句代码警告:

Default argument value is mutable

意思是告诉我们函数的定义中,使用可变类型做默认参数。

那为什么会有这个警告呢?

可变类型和不可变类型

  • 可变类型(mutable):列表,字典
  • 不可变类型(unmutable):数字,字符串,元组

定义可变类型会有什么问题?

def fun(a=[]):
    a.append(1)
    print(a)
if __name__ == "__main__":
    fun()
    fun()
>>> [1]
    [1, 1]

可以发现,默认参数定义可变类型之后,在第二次乃至更多次地调用同一个函数时,默认参数仿佛失去了效果。

此时,在需要重复调用同一个函数的场景中,就非常容易导致问题,并且该问题不易察觉。在debug的时候就会表现成明明没有参数传进来,但是函数参数会有值,并且执行了不应该执行的操作。

导致的原因

我的理解:

我们定义的函数本身是一个function的实例化对象,每当我们进行函数的定义时,就是创建了一个function的实例化对象,而默认参数就是其属性。

在没有传入参数,以默认参数形式调用,并且改变了函数对象的属性值时,改变的属性值被保存下来,当第二次调用同一个对象时,属性值已经发生了改变。

type(fun)
>>> function

解决方法

def fun(a=None):
    if a is None:
    a = []
    a.append(1)
    print(a)
if __name__ == "__main__":
    fun()
    fun()
>>> [1]
    [1]

关于可变类型作为默认参数时的注意点

请先看代码,看看代码的输出是否和你想的一样。

def e(v,l=[]):
    l.append(v)
    return l
l1=e(10)
l2=e(123,[])
l3=e("a")
print(l1,l2,l3)
# 输出: ([10, 'a'], [123], [10, 'a'])

关于上述代码,标准解释是:带有默认参数的表达式在函数被定义的时候被计算,不是在调用的时候计算。

我觉得通俗的解释是:当不传默认值的时候,无论调用多少次该函数,在函数体内部使用的一直都是那个默认的“l”,而这个默认的“l”又是可变类型,所以,它的改变会影响所有指向它的变量,也就是l1和l3。

为了使以上两点的观点更加站的住脚,我进行以下几个测试。

测试:将可变类型列表换为字典

def e(k,v,d={}):
    d[k]=v
    return d
d1=e(10,10)
d2=e(123,123,{})
d3=e("a","a")
print(d1,d2,d3)
# 输出:({'a': 'a', 10: 10}, {123: 123}, {'a': 'a', 10: 10})

测试:来个不可变类型字符串

def e(v,s=""):
    s = s+v
    return s
s1=e("我")
s2=e("a","")
s3=e("是")
print(s1,s2,s3)
# 输出: 我 a 是

其实以上类型都已经说明问题了,但是写个文章不容易,我决定用元祖包列表,看看修改这个列表中的数据会怎样。

实际上是不用测试的,最终打印出来的数据一定是类似**“可变类型时的操作”**时的输出的。

为什么?因为我没有修改元祖本身,修改的是其可变类型列表啊。

不能扯远了,不然扯到深拷贝,浅拷贝了。

测试:元祖包个列表来

def e(v,t=([],)):  # 传递有元素的元祖的时候要记得带逗号哦。
    
    t[0].append(v)
    # t = t[0].append(v)     要知道t[0].append(v)是没有返回值的,t会指向None,如果这样返回,外部打印的全部为None,所以不可以这样返回。
    # 而且 如果你想 t[0]= t[0].append(v) 也是不行的,为啥?你在ipython中输入 dir(())你就知道了。
    # 好吧,其实是因为元祖是可读不可写的。它能切片、遍历就已经很不错了。。。。。
    return t
t1=e("我")
t2=e("a",([],))
t3=e("是")
print(t1,"\n",t2,"\n",t3)
# 输出:
# (['我', '是'],) 
# (['a'],) 
# (['我', '是'],)

小结一下

家里停电了,所以我来到了网吧,这篇文章是在网吧写的,用的是python3的在线编辑器,有的地方编码(比如命名-。-)或者表述的不好请多多见谅。

关于集合,我就不做测试了,集合一般用于去重和关系运算,它是无序,不重复,可变类型。 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

python函数的默认参数请勿定义可变类型详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

python函数的默认参数为什么不可以定义可变类型

这篇文章主要介绍“python函数的默认参数为什么不可以定义可变类型”,在日常操作中,相信很多人在python函数的默认参数为什么不可以定义可变类型问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”python函
2023-06-29

C++ 函数的默认参数和可变参数详解

c++++ 默认参数允许为函数参数设置默认值,而在可变参数中,可以为函数提供任意数量的参数。具体而言:默认参数:允许在函数声明时为参数指定默认值,在调用时如果没有提供值则使用默认值。可变参数:使用 ... 表示,允许函数接受任意数量的参数,
C++ 函数的默认参数和可变参数详解
2024-04-19

Python---限定函数参数的类型及默

python作为一门动态语言,在使用变量之前是不需要进行定义,而是通过动态绑定的方法将变量绑定为某种类型。这样做为我们使用变量时提供了方便,但有时也给我们使用变量时造成了一定的困扰,例如在使用变量时不知道变量的类型,使用函数时不知道该传什么
2023-01-31

如何为 PHP 函数指定参数的默认类型

为 php 函数指定参数的默认类型可以提高代码的可读性、加强类型检查和提供自动类型转换。这适用于 php 7.0 及更高版本,语法为:function funcname(type $paramname, type $paramname2):
如何为 PHP 函数指定参数的默认类型
2024-04-19

C++ 函数默认参数和可变参数在泛型编程中的作用

c++++ 中的默认参数和可变参数在泛型编程中发挥着至关重要的作用:默认参数允许函数在调用时指定可选参数,便于处理不同类型和默认值的元素。可变参数允许函数接受任意数量的参数,便于处理可变数量的元素。实战案例中,泛型容器(例如 vector
C++ 函数默认参数和可变参数在泛型编程中的作用
2024-04-22

Python中如何自定义函方法与参数具有默认值的函数

这篇“Python中如何自定义函方法与参数具有默认值的函数”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python中如何自
2023-06-29

C/C++宏定义的可变参数详细解析

在1999年版本的ISO C 标准中,宏可以象函数一样,定义时可以带有可变参数。宏的语法和函数的语法类似
2022-11-15

泛型函数在Golang中解决可变参数类型的问题吗?

go 中的泛型函数解决了可变参数类型的问题:泛型函数允许使用类型参数,在运行时指定。这使得编写可以处理不同类型参数的函数成为可能。例如,max 函数是一个泛型函数,它接受两个可比较参数并返回较大值。通过使用泛型函数,我们可以编写更灵活通用的
泛型函数在Golang中解决可变参数类型的问题吗?
2024-04-16

小议Python中自定义函数的可变参数的使用及注意点

可变参数 Python的可变参数有两种,一种是列表类型,一种是字典类型。列表类型类似 C 中的可变参数,定义方式为def test_list_param(*args) :for arg in args :print arg其中 args 是
2022-06-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录