我正在尝试创建一个代码,用于删除用户定义范围内的奇数(例如,在 4 到 10 之间(。到目前为止,我有这个:
def even(x,y):
if x > y:
return None
else:
s = list(range(x, y+1))
for i in s:
if s[i]%2!=0:
del s[i]
return s
even(4,10)
当我运行代码时,它返回 [4, 5, 6, 7, 8, 10] 而不是 [4, 6, 8, 10]。知道为什么吗?
创建一个更大的集合,然后删除不需要的项目是没有意义的。
我怀疑如果您只是使用您想要的内容创建列表会更好:
def even(lo, hi):
if lo > hi: return None # although [] may make more sense
return [item for item in range(lo, hi + 1) if item % 2 == 0]
我之所以声明在lo > hi
的情况下返回[]
可能更好,是因为这是为其他边缘情况(例如even(3,3)
(返回的内容。
根据以下成绩单,这给出了您想要的内容:
>>> def even(lo, hi):
... if lo > hi: return None
... return [item for item in range(lo, hi + 1) if item % 2 == 0]
...
>>> even(4, 10)
[4, 6, 8, 10]
你的代码有 3 个问题。
-
使用
s[i]
访问列表的第i
项,但i
已经保存了列表项,因为您执行了for i in s:
:>>> s = list(range(4, 11)) >>> s [4, 5, 6, 7, 8, 9, 10] >>> for i in s: ... print(i) ... 4 5 6 7 8 9 10
您的循环实际上正在与
s[i]
一起检查的是:>>> for i in s: ... print(s[i]) ... 8 # i=4, s[4] 9 # i=5, s[5] 10 # i=6, s[6]
-
当你找到一个奇数(
s[5]=9
,9%2 != 0
(时,你会立即因为return s
而脱离循环。因此,您的循环只会删除它找到的第一个奇数,然后立即脱离循环。也许它只是错误地缩进了,但
return s
应该在函数的末尾,而不是在循环内。 -
在循环访问列表时,您正在从列表中删除项目。这从来都不是一个好主意,因为这会搞砸循环。
>>> s = list(range(4, 11)) >>> for idx, i in enumerate(s): ... print(i) ... if i%2 != 0: ... print("removing i") ... del s[idx] ... 4 5 removing i 7 # notice that 6 was now skipped after removing 5 removing i 9 # notice that 8 was now skipped after removing 7 removing i
话虽如此,正确的方法是遍历输入列表,但结果/输出应该在不同的列表中。这样,循环就不会搞砸。最简单(也是最"pythonic"(的方法是使用列表理解:
def even(x,y):
if x > y:
return None
else:
s = list(range(x, y+1))
return [d for d in s if d % 2 == 0]
或者,您可以使用while
手动循环,然后跟踪正确的列表索引:
def even(x,y):
if x > y:
return None
else:
s = list(range(x, y+1))
idx = 0
while idx < len(s):
if s[idx]%2!=0:
del s[idx]
# after this, s[idx] now points to the next item
else:
idx += 1
# move to the next item
return s
这是正确的代码。 您可以在 Python 中按项目列表和按索引 del 中删除:
def even(x,y):
if x > y:
return None
else:
s = list(range(x, y+1))
for i in s:
if i%2 != 0:
s.remove(i)
return s
even(4,10)