Python默认参数列表-行为不一致

时间:2019-07-23 13:18:35

标签: python list function

我遇到的情况是,函数头中默认参数的值受函数体内的if子句影响。我正在使用Python 3.7.3。

功能定义

我们有两个功能fj。我了解前两个功能的行为。我不了解第二个功能的行为。

def f(L=[]):
    print('f, inside:   ', L)
    L.append(5)
    return L

def j(L=[]):
    print('j, before if:', L)
    if L == []:
        L = []
    print('j, after if: ', L)
    L.append(5)
    return L

我了解的功能行为

现在我们调用第一个函数三次:

>>> print('f, return:   ', f())
f, inside:    []
f, return:    [5]
>>> print('f, return:   ', f())
f, inside:    [5]
f, return:    [5, 5]
>>> print('f, return:   ', f())
f, inside:    [5, 5]
f, return:    [5, 5, 5]

空列表[]在函数的第一次调用时初始化。当我们将5附加到L时,将修改内存中列表的一个实例。因此,在第二个函数调用上,将此修改后的列表分配给L。听起来很合理。

我不了解的功能行为

现在,我们调用第三个函数(j)并获得:

>>> print('j, return:   ', j())
j, before if: []
j, after if:  []
j, return:    [5]
>>> print('j, return:   ', j())
j, before if: []
j, after if:  []
j, return:    [5]
>>> print('j, return:   ', j())
j, before if: []
j, after if:  []
j, return:    [5]

根据输出,L在每次调用函数j的开头都是一个空列表。当我删除if子句时,在函数j的主体中,该函数等于函数f并产生相同的输出。因此,if子句似乎有一些副作用。测试len(L) == 0而不是L == []中的j具有相同的效果。

相关

我的问题与以下方面有关:

但是这些问题的答案和本教程仅回答了我已经知道的事情。

3 个答案:

答案 0 :(得分:1)

如果全部归结为:

if L == [5]:
    L = []

在这里,您无需更改默认参数的值,只需在本地绑定到新名称即可。

您可以改为:

if L == [5]:
    L.clear()

if L == [5]:
    L[:] = []

清除参数对象的数据。

答案 1 :(得分:1)

修改打印语句以同时打印id(L)

def j(L=[]):
    print('j, before if:', L, id(L))
    if L == []:
        L = []
    print('j, after if: ', L, id(L))
    L.append(5)
    return L

现在检查结果:

>>> j()
j, before if: [] 2844163925576
j, after if:  [] 2844163967688
[5]

请注意ID的差异。当您到达修改L的函数部分时,它不再与默认参数引用同一对象。您已经将L反弹到一个新列表(其中L = []位于if语句的主体中),因此,您永远不会更改默认参数。

答案 2 :(得分:0)

def a():
    print "assigning default value"
    return []

def b(x=a()):
    x.append(10)
    print "inside b",x
    return x

print b()
print b()
print b()

尝试运行它。您会看到每次运行该函数时都未分配默认值 输出

assigning default value
inside b [10]
[10]
inside b [10, 10]
[10, 10]
inside b [10, 10, 10]
[10, 10, 10]

仅一次将'a'函数调用为默认值。上面在方法的编译方面对其余部分进行了很好的解释,因此不再重复相同的操作