当遍历函数内部的列表时,为什么0不是0.0?

时间:2018-12-17 16:39:51

标签: python list floating-point

我正在尝试解决一个问题,其中必须从列表中删除零(00.0)并将其添加到列表的末尾(附加的零)可以是0,而不必是0.0)。但是要注意的是,我不能删除False。我以为我终于通过使用is而不是==来解决了我的问题,但是由于某些原因,它不起作用:

arr = [9,0.0,0,9,1,2,0,1,0,1,0.0,3,0,1,9,0,0,0,0,9]
def move_zeros(array):
    temp = array.copy()
    j = 0
    for p, i in enumerate(array):
        if i is 0 or i is 0.0:
            del temp[p - j]
            j += 1
            temp.append(0)
    return temp

print(move_zeros(arr))

我尝试在if语句中加上括号,但结果是相同的。它会删除所有的0,但是由于某种原因它不会删除0.0。结果:

[9, 0.0, 9, 1, 2, 1, 1, 0.0, 3, 1, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0]

我重写了该函数,但在该函数之外,并且由于某种原因它起作用了

array = [1, 0, 2, False, 0.0, 4]
for p, i in enumerate(array):
    if i is 0 or i is 0.0:
        del temp[p - j]
        j += 1
        temp.append(0)

结果就是我所期望的:

[1, 2, False, 4, 0, 0]

为什么在函数外执行浮点零运算,但是调用函数move_zeros却不能在if语句中识别浮点运算?

2 个答案:

答案 0 :(得分:2)

您只能处理floatsints-如果值不为0,则可以从输入中构造新列表:

arr = [9,0.0,0,9,1,2,0,1,0,1,0.0,3,0,1,9,0,0,0,0,9]

def move_zeros(array):
    len_arr = len(array)
    return ([ x for x in array if x != 0.0]+[0]*len_arr)[:len_arr]

# equivalent non-listcomprehension but simple for loop
def m_z(arr):
    k = []
    tmp = []
    for e in arr:
        if e/1.0 != 0.0:
            k.append(e)
        else:
            tmp.append(0)
    return k+tmp

    print(move_zeros(arr))

输出:

[9, 9, 1, 2, 1, 1, 3, 1, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

如果x是整数,只有0-0可以导致0.0-如果x是浮点数,则只有0.0-0.0可能导致0.0-根本不要将它们放入输出中。不需要.copy(),因为列表理解已经为您复制了。

检查整数和is之所以有效,是因为python缓存了从-5到256左右的整数-它们都具有相同的id(),因此is“似乎”可以工作。

仅将is用于None支票,或者如果您知道自己要做什么,则永远不要用于数字。

如果您想保持非(ìnt,float)的原样,也可以进行检查:

arr = [9,0.0,0,False,9,1,2,0,1,0,1,0.0,3,0,1,9,0,0,0,0,9]

def move_zeros(array):
    len_arr = len(array)
    return ([ x for x in array if type(x) not in {int,float} or 
             x != 0.0]+[0]*len_arr)[:len_arr]

# [9, False, 9, 1, 2, 1, 1, 3, 1, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

了解更多:


健全性检查:

k = 365
i = 365 // 5 * 5  # if you do i = 365 only, they are ==/is True, this way: they are not

for elem in [0,False,k]:
    for olem in [0,False,i]:     
        print(f"{str(elem):>8} is {str(olem):<10}:   {str(elem is olem):<10} ")
        print(f"{str(elem):>8} == {str(olem):<10}:   {str(elem == olem):<10} ")

输出:

       0 is 0         :   True       
       0 == 0         :   True       
       0 is False     :   False      
       0 == False     :   True       
       0 is 365       :   False      
       0 == 365       :   False      
   False is 0         :   False      
   False == 0         :   True       
   False is False     :   True       
   False == False     :   True       
   False is 365       :   False      
   False == 365       :   False      
     365 is 0         :   False      
     365 == 0         :   False      
     365 is False     :   False      
     365 == False     :   False      
     365 is 365       :   False      # k is i
     365 == 365       :   True       # k == i

答案 1 :(得分:1)

使用==,而不是isis用于比较身份(本质上两个“事物”在内存中占据相同的空间),==用于相等性(两个事物具有相同的定义属性)。此外,对于浮子,检查物体是否“足够靠近”通常是有用的。 is_equal = a-b < 0.00001