python 关于可变类型作为默认参数时的注意点

摘要

  • 请先看代码,看看代码的输出是否和你想的一样。
def e(v,l=[]):
	l.append(v)
	return l

l1=e(10)
l2=e(123,[])
l3=e("a")

print(l1,l2,l3)

# 输出: ([10, 'a'], [123], [10, 'a'])
  • 关于上述代码,标准解释是:带有默认参数的表达式在函数被定义的时候被计算,不是在调用的时候计算。
  • 我觉得通俗的解释是:当不传默认值的时候,无论调用多少次该函数,在函数体内部使用的一直都是那个默认的“l”,而这个默认的“l”又是可变类型,所以,它的改变会影响所有指向它的变量,也就是l1和l3。
  • 为了使以上两点的观点更加站的住脚,我进行以下几个测试。
测试:将可变类型列表换为字典。
def e(k,v,d={}):
	d[k]=v
	return d

d1=e(10,10)
d2=e(123,123,{})
d3=e("a","a")

print(d1,d2,d3)

# 输出:({'a': 'a', 10: 10}, {123: 123}, {'a': 'a', 10: 10})

测试:来个不可变类型字符串
def e(v,s=""):
	s = s+v
	return s

s1=e("我")
s2=e("a","")
s3=e("是")

print(s1,s2,s3)

# 输出: 我 a 是

  • 其实以上类型都已经说明问题了,但是写个文章不容易,我决定用元祖包列表,看看修改这个列表中的数据会怎样。
  • 实际上是不用测试的,最终打印出来的数据一定是类似**“可变类型时的操作”**时的输出的。
  • 为什么?因为我没有修改元祖本身,修改的是其可变类型列表啊。
  • 不能扯远了,不然扯到深拷贝,浅拷贝了。
测试:元祖包个列表来
def e(v,t=([],)):  # 传递有元素的元祖的时候要记得带逗号哦。
	
	t[0].append(v)
	# t = t[0].append(v)     要知道t[0].append(v)是没有返回值的,t会指向None,如果这样返回,外部打印的全部为None,所以不可以这样返回。
	# 而且 如果你想 t[0]= t[0].append(v) 也是不行的,为啥?你在ipython中输入 dir(())你就知道了。
	# 好吧,其实是因为元祖是可读不可写的。它能切片、遍历就已经很不错了。。。。。
	return t

t1=e("我")
t2=e("a",([],))
t3=e("是")

print(t1,"\n",t2,"\n",t3)
# 输出:
# (['我', '是'],) 
# (['a'],) 
# (['我', '是'],)

总结

  • 家里停电了,所以我来到了网吧,这篇文章是在网吧写的,用的是python3的在线编辑器,有的地方编码(比如命名-。-)或者表述的不好请多多见谅。
  • 关于深拷贝和浅拷贝请参考百度吧,我刚刚翻了翻我的博客,里面暂时没有相关文章。
  • 关于集合,我就不做测试了,集合一般用于去重和关系运算,它是无序,不重复,可变类型。
发布了55 篇原创文章 · 获赞 3 · 访问量 2745

猜你喜欢

转载自blog.csdn.net/rusi__/article/details/102854817
今日推荐