一般来说,函数的默认参数都用不可变对象来作默认参数,如int,str,None,tuple,bool等。
举例:
def func(x,y=2):
return x+y
func(1)
>>>print(func(1))
3
>>>print(func(1,10))
11
在实际工程中,经常会用None和bool来作默认参数,在使用None作默认参数的时候,函数内部的判断务必用:if param is None
或者 if parma==None
都可以,None是一种特殊的类型Nonetype, 通过is比较id地址或者通过==比较值,都可以准确判定。但是不要使用if not param:
,因为除了None,空字典,空字符,空列表等也会通过判定,无法被过滤掉。
举例:
def func(y=None):
if not y:
print(‘10000‘)
else:
print(‘ttttt‘)
>>>func(1)
ttttt
>>>func()
10000
>>>func([])
10000
>>>func(‘‘)
10000
>>>func({})
10000
?
因此对None的判定不要用not。
一般不要用可变对象作为默认参数,后续如果对可变对象进行了增删改,会不断影响到下一次调用时默认参数的值。举例:
def func(x,y=[1]):
return y
>>>m=func(1)
>>>m
[1]
>>>n=func(1,[1,2,3])
>>>n
[1, 2, 3] ###到这里都没有任何问题
?
#这里去改变之前的m
>>>m.append(4)
>>>m.append(‘test‘)
>>>m
>>>[1, 2, 3, 4, ‘test‘]
?
#重新去调用函数,发现这个时候里面的默认参数y已经跟着改了
>>>q=func(1)
>>>q
[1, 2, ‘test‘]
因此,默认参数用可变对象非常容易造成代码出现预期之外的问题。
什么原因?
本质原因就是赋值,浅拷贝,深拷贝之间的问题。上述例子的本质流程:
m=y
m.append(4)
m.append(‘test‘)
因为y是可变对象,赋值操作只是类似取了一个别名,两个变量存的地址id一样,即都是引用的对象[1],当对象内部变了,回来会同时影响m和y。
def func(x,y=[1]):
print(id(y))
return y
>>>m=func(1)
2665443856192
>>>print(id(m))
2665443856192
如果实在想用某个可变对象做默认参数怎么办?比如在最近一个项目中,一个类的入参我想传如一个list,但这个list又想用[0]来作为默认参数,可以这样实现:
def func(x:int,y=None):
if y is None:
y=[0]
else:
if not isinstance(list,type(y)):
raise Exception(‘y must be list!‘)
return y
?
>>>print(func(1))
0
>>>func(1,[1,2,3])
[1,2,3]
>>>func(1,1)
Traceback (most recent call last):
File "<input>", line 11, in <module>
File "<input>", line 7, in func
Exception: y must be list!
原文:https://www.cnblogs.com/qianfanwaer/p/14792106.html