一个账号 发表于 2021-1-5 21:36:10

默认参数最好不为可变对象

本帖最后由 一个账号 于 2021-1-5 22:25 编辑

在之前写的一个项目中,就遇到这个错误。

在传递默认参数时,新手很容易遇到这个错误。

这个错误是什么呢?我们来看一个例子:

>>> def func(va, li=[]):
        li.append(va)
        print(li)

       
>>> func("A")
['A']
>>> func("B", ["C", "D"])
['C', 'D', 'B']
>>> func("E")
--------- 隐藏 ---------
>>>

你们猜猜最后输出的是什么呢?

>>> def func(va, li=[]):
        li.append(va)
        print(li)

       
>>> func("A")
['A']
>>> func("B", ["C", "D"])
['C', 'D', 'B']
>>> func("E")
['A', 'E']
>>>

Python 中的 def 语句在每次执行的时候都初始化一个函数对象,这个函数对象就是我们要调用的函数,

可以把它当成一个一般的对象,只不过这个对象拥有一个可执行的方法和部分属性。

对于参数中提供了初始值的参数,由于 Python 中的函数参数传递的是对象,

也可以认为是传地址,在第一次初始化 def 的时候,会先生成这个可变对象的内存地址,

然后将这个默认参数 li 会与这个内存地址绑定。在后面的函数调用中,如果调用方指定了新的默认值,

就会将原来的默认值覆盖。如果调用方没有指定新的默认值,那就会使用原来的默认值。

============================================分割线============================================

在这个帖子中顺便也写一下最近发现的一个有趣的事情

来看一个简单的例子:

li =
print(li)

执行一下,和我们的预期一样,会抛出索引错误:

IndexError: list index out of range

但是大家来看看这个例子:

li=
print(li)

最后会输出一个空列表

[]

Mike_python小 发表于 2021-1-7 14:00:09

真不错{:10_256:}

柿子饼同学 发表于 2021-3-14 15:50:04

可以可以{:10_275:}

crisfo 发表于 2021-3-14 16:26:33

那么,避免这个问题的方法是什么呢?{:5_99:}

至秦臻 发表于 2021-3-14 16:31:56

真可以{:10_275:}

程序员不秃 发表于 2021-3-14 17:21:43

crisfo 发表于 2021-3-14 16:26
那么,避免这个问题的方法是什么呢?

这个完全 是因为你列表中没有这么长的字符,不需要避免,按照自己列表的长度,来截取字符串就可以了

crisfo 发表于 2021-3-15 07:43:34

程序员不秃 发表于 2021-3-14 17:21
这个完全 是因为你列表中没有这么长的字符,不需要避免,按照自己列表的长度,来截取字符串就可以了

不好意思,没表述清楚,我说的是 li = [] 的问题
页: [1]
查看完整版本: 默认参数最好不为可变对象