Python之函数参数中的默认参数使用list的特殊情况

Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数。但需要注意的是:

  • 一是必选参数在前,默认参数在后,否则Python的解释器会报错(思考一下为什么默认参数不能放在必选参数前面);
  • 二是如何设置默认参数。

当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。

使用默认参数有什么好处?最大的好处是能降低调用函数的难度。

举个例子,我们写个一年级小学生注册的函数,需要传入namegender两个参数:

def enroll(name, gender):
    print('name:', name)
    print('gender:', gender)

这样,调用enroll()函数只需要传入两个参数:

>>> enroll('Sarah', 'F')
name: Sarah
gender: F

如果要继续传入年龄、城市等信息怎么办?这样会使得调用函数的复杂度大大增加。

我们可以把年龄和城市设为默认参数:

def enroll(name, gender, age=6, city='Beijing'):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)

这样,大多数学生注册时不需要提供年龄和城市,只提供必须的两个参数:

>>> enroll('Sarah', 'F')
name: Sarah
gender: F
age: 6
city: Beijing

只有与默认参数不符的学生才需要提供额外的信息:

enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')

可见,默认参数降低了函数调用的难度,而一旦需要更复杂的调用时,又可以传递更多的参数来实现。无论是简单调用还是复杂调用,函数只需要定义一个。

有多个默认参数时,调用的时候,既可以按顺序提供默认参数,比如调用enroll('Bob', 'M', 7),意思是,除了namegender这两个参数外,最后1个参数应用在参数age上,city参数由于没有提供,仍然使用默认值。

也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上。比如调用enroll('Adam', 'M', city='Tianjin'),意思是,city参数用传进去的值,其他默认参数继续使用默认值。

默认参数很有用,但使用不当,也会掉坑里。默认参数有个最大的坑,演示如下:

先看一段代码

1

2

3

4

5

6

7

8

9

def f(x,l=[]):

    for in range(x):

        l.append(i*i)

    print(l)

print('---1---')

f(4)

print('---2---')

f(5)

执行结果:

1

2

3

4

---1---

[0149]

---2---

[0149014916]

预期的结果为:

1

2

3

4

---1---

[0149]

---2---

[014916]

问题解释:当定义函数时,会保存函数中默认参数list的值,也就是列表[],在每次调用的时候如果传递了列表,则使用传递的列表,没有传递,使用定义函数时保存的默认参数list,以上案例中两次调用都没有传递默认参数list,程序会调用定义函数时,保存的默认参数list,列表在append的时候回在原来的基础上添加,所以会产生以上结果,我们可以通过打印id看出。

修改代码:

1

2

3

4

5

6

7

8

9

10

11

def f(x,l=[]):

    print(id(l))  # 添加打印id

    for in range(x):

        l.append(i*i)

    print(l)

print('---1---')

f(4)

print('---2---')

f(5)

结果:

1

2

3

4

5

6

---1---

140306123906248

[0149]

---2---

140306123906248

[0149014916]

会发现id值是相同的,说明两次执行时使用的都是定义函数时默认的参数

再次修改代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

def f(x,l=[]):

    print(id(l))

    for in range(x):

        l.append(i*i)

    print(l)

print('---1---')

f(4)

print('---2---')

f(5,[])

print('---3---')

f(6)

结果:

1

2

3

4

5

6

7

8

9

---1---

140017293614280

[0149]

---2---

140017293614472

[014916]

---3---

140017293614280

[014901491625]

会发现执行传递空列表的函数时打印的id不一样,而没有传递的一样。当传递空list时函数体当中会使用传递的空list,没有传递时,使用函数默认的list。所以会产生以上结果

如果想要达到预期的结果编写一下代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

def f(x,l=None):

    if is None:

        = []

    for in range(x):

        l.append(i*i)

    print(l)

print('---1---')

f(4)

print('---2---')

f(5)

print('---3---')

f(6)

结果:

1

2

3

4

5

6

---1---

[0149]

---2---

[014916]

---3---

[01491625]

 这样就达到了预期的结果。

猜你喜欢

转载自blog.csdn.net/lovedingd/article/details/128216474
今日推荐