先把测试代码贴上,以后再整理解释
def f1(a, b, c=1, d='abc'):
print('a={}'.format(a))
print('b={}'.format(b))
print('c={}'.format(c))
print('d={}'.format(d))
def f2(a=[]): # 该定义不正确,默认参数指定的值必须是一个不可变类型,此处可以用 a = None
a.append(1)
return a
def f3(a, b, c=1, d='abc', *args, **kwargs):
print('a={}'.format(a))
print('b={}'.format(b))
print('c={}'.format(c))
print('d={}'.format(d))
print(args)
print(kwargs)
if __name__ == "__main__":
# f1(1, 2)
# f1(1, 2, 3, 4)
# f1(1, 2, d='345')
# f1(1, 2, d='212', c=3) #以上调用均正确
print(f2()) # [1]
print(f2()) # [1][1]
print(f2()) # [1][1][1]
# 默认参数设置为一个可变类型会输出以上结果
# 解释:原因是当执行这个模块时,函数只会被加载一次,
# 并且它的默认参数也会被设置在这个函数对象的defaults属性中(可以用 print(f2.__defaults__)查看)
# 当我们三次调用该函数都没有传递参数时,a.append(1)
# 就会在同一个列表对象上进行操作,于是就得到这样一个结果。
f3(1, 2, 3, 4, 5, 6, 7, abc='222', bcd=234) # 正确调用
f3(1, 2, c=1, d='123') # 正确调用
# f3(1, 2, c=1, d='123',2,4,5) # 错误调用(python没有把后面的2,4,5当成你要传到args中的值,而是把他们当成了与之前1,2
# 相同的位置参数)
f3(1, 2, 3, 4, 5, 6, 7, abc=345, you=23) # 正确调用,1,2,3,4依次赋值给abcd,args接受了后面的 567,kwargs接受了abc和you
li = [11, 22, 33, 44]
di = {'one': 1, 'two': 2, 'three': 3}
f3(1, 2, 3, 4, 5, 6, 7, 8, *li, abc=123, **di) # 正确的解包调用,5678与拆包后的li一起被args接收,
# abc与拆包后的di一起被kwargs接收
# 总结:python函数传递有两个注意点:
# 1、定义函数时,如果使用默认参数,不能给其赋予默认值为可变类型,如果要传入可变类型使用*args和**kwargs,或者默认值指定为None
# 2、调用函数时,如果被调用函数是各种混合参数,传入的参数要注意顺序,即便是前面有默认值参数,也不能在前面指定参数赋值,
# 在后面才能指定参数赋值