1. 引言
在Python学习中,经常会遇到各种各样的代码错误,尤其对于初学者而言,明明觉得逻辑上是对的,但是代码运行起来,往往不是自己想要的结果。
本文就最近在某平台看到的一个常见错误进行展开,帮助大家更好的理解Python的基础语法,闲话少说,我们直接开始吧!
2. 问题描述
首先,我们来检查以下代码,看看其中是否有问题?该代码的目的是删除列表中的偶数。
思考两分钟,你认为上述代码的运行结果会是什么?
[1, 7, 11]
是我们所希望输出的,上述代码看起来似乎也没有问题。但是上述代码的运行结果是[1, 7, 8, 11]
,这里的数字8
哪里来的?
3. 问题解析
上述代码输出包括数字8
,是因为代码在遍历列表时会从列表中删除元素,会导致列表发生变化。我们修改上述代码,将每次for
循环中的临时变量都进行输出,代码如下:
def remove_even(nums):
for i,num in enumerate(nums):
print("i={} num={}".format(i,num))
if num%2==0:
del nums[i]
nums=[1,2,7,4,8,11]
remove_even(nums)
print(nums)
运行结果如下:
i=0 num=1
i=1 num=2
i=2 num=4
i=3 num=11
[1, 7, 8, 11]
上述运行过程如下:
- 当
i=0
时,此时num=1
,不满足偶数判断,结束本次循环。 - 当
i=1
时,此时num=2
,满足偶数判断,此时删除nums[1]
,则此时列表将变化为[1,7,4,8,11]
; - 当
i=2
时,此时num=4
,满足偶数判断,此时删除nums[2]
,则此时列表将变化为[1,7,8,11]
; - 当
i=3
时,此时num=11
,不满足偶数判断,循环结束。最后列表变为[1,7,8,11]
。
4. 解决方案一
为了避免这个问题,最好创建一个新的列表只用来存储不满足条件语句的元素,而不是在迭代时修改原始列表。例如:
上述代码运行后将会输出[1,7,11]
,这就时我们所希望的结果。当然还有其他更优雅的实现方式。
5. 解决方案二
yield
是Python中的一个关键字,用于定义生成器函数。生成器是一种特殊类型的函数,可以用来动态生成一系列值,而不是像常规函数那样一次返回所有值。当在生成器函数中执行yield语句时,它会暂时挂起函数的执行,并通过yield
关键字返回表达式的值。函数并没有终止,而是处于挂起状态,后续可以继续从挂起的地方恢复。
用yield
关键字实现上述功能的样例代码如下:
在这段代码中,remove_even
是一个生成器函数,它从输入的列表numbers
中每次产生一个奇数。然后使用list()
构造函数将remove_even
返回的生成器对象转换成列表。使用生成器还允许对大的或无限的数据序列进行更灵活和存储器高效的处理。
6. 总结
本文重点介绍了在Python中删除列表元素时初学者容易犯的低级错误,并针对性的提出了两种解决方法,可以更加灵活和高效的处理更大规模的数据列表。
嗯嗯,您学废了嘛?