写python程序时有些陷阱需要注意,不然就会对bug视而不见,或者得不到想要的结果。
list的append无返回值
list列表的append函数只做原位(in place)操作,改变原有的列表的内容,而不是返回一个新的列表。
>>> a = [1, 2, 3]
>>> a.append(4)
>>> a
[1, 2, 3, 4]
>>> b = a.append(5)
>>> print b
None
>>> print a
[1, 2, 3, 4, 5]
>>>
list的sort无返回值
与append函数类似,sort也只做原位(in place)操作,在原有的列表内排序,而不返回一个新的列表。
shelve对象
>>> import shelve
>>> s = shelve.open('test.dat')
>>> s['x'] = ['a', 'b', 'c']
>>> s['x'].append('d')
>>> s['x']
['a', 'b', 'c']
上面的例子里,shelve的open函数返回的对象虽然看起来和普通的列表一样,但是在调用sync()之前,它的值不会发生改变,所以,当s[‘x’]再次被读取时,仍然是原始的值,’d’字符没有保存进shelve
新建默认值为空的字典
这个话题在 这篇文章 中单独介绍
在列表中循环的同时,删除列表元素
假设我们需要从一个列表中去除部分元素,比如从下面的列表:
[0,1,2,3,4,5,6,7,8,9] # list(range(10))
中,删除所有大于5的元素。我们试着这么写:
a = list(range(10))
for x in a:
if x > 5:
a.remove(x)
print(a) # [0, 1, 2, 3, 4, 5, 7, 9]
没有得到想要的,我们换种实现方法:
a = list(range(10))
for i, x in enumerate(a):
if x > 5:
del a[i]
print(a) # [0, 1, 2, 3, 4, 5, 7, 9]
使用 remove()
或者 del
得不到期望的结果的原因是:当找到第一个大于 5 的元素 6 时,索引 i=6,这时候删除元素6,后面的元素向前移动,7到了原来6的位置,索引 i=6 指向了7,索引 i=7指向了8。
于是下一个循环中,将判断 索引 i=7 的值是否大于5,由于7向前移了一位,“逃过了” 检查,所以就保留在了原数组中。
那么有没有办法解决这个问题?有两个办法
- 列表解析的方法是可行的:
a = list(range(10))
print([x for x in a if x < 5]) # [0, 1, 2, 3, 4]
- 将原数组复制一个备份出来,只要在后面加上
[:]
即可
a = list(range(10))
for x in a[:]:
if x > 5:
a.remove(x)
print(a) # [0, 1, 2, 3, 4, 5]
如果您对本文有疑问或者寻求合作,欢迎 联系邮箱 。邮箱已到剪贴板
标签: PYTHON
给个免费的赞吧~
精彩评论
本站 是个人网站,采用 署名协议 CC-BY-NC 授权。
欢迎转载,请保留原文链接 https://www.lfhacks.com/tech/python-traps/ ,且不得用于商业用途。