【问题标题】:Issue when removing false from list with isinstance使用 isinstance 从列表中删除 false 时出现问题
【发布时间】:2017-05-17 00:04:51
【问题描述】:

所以,我在 Python 中从列表中删除非整数(非常令人兴奋的东西)。我遇到了以下代码的问题,我似乎无法解决:

list_a = ["a", 1, 2, 3, False, [1, 2, 3]]

for item in list_a:
    if not isinstance(item, int):
        list_a.remove(item)

我正在尝试删除列表中的所有非 int 项,但上述代码并未删除 False。

我想要什么:[1, 2, 3]

我得到了什么:[1, 2, 3, False]

任何解决此问题的帮助将不胜感激!

【问题讨论】:

  • False为值,为0,为整数!
  • False 在内部表示为整数 0。实际上 False==0True - 但 False is 0 不是。使用运算符is 删除False
  • 其他问题:您在迭代列表时在列表中移动项目。不要那样做。建立一个新列表。

标签: python list python-3.x boolean


【解决方案1】:

您的问题是bool int 的子类:

>>> issubclass(bool, int)
True

因此,所有布尔值都是整数(其中 False 为 0,True 为 1)并且可以用于索引等。您可以改为测试type(item) is bool

【讨论】:

    【解决方案2】:

    在 Python 中,boolint 的子类:

    >>> isinstance(True, int)
    True
    >>> isinstance(True, bool)
    True
    

    这意味着您需要更精细的检查。例如,您可以检查 type(item) == int

    背景见PEP 285:

    6) bool 是否应该从 int 继承? => 是的。 在理想的世界中,bool 可能更好地实现为 知道如何执行混合模式的单独整数类型 算术。但是,从 int 继承 bool 可以简化 极大地实现(部分原因是所有调用的 C 代码 PyInt_Check() 将继续工作——这将返回 true int 的子类)。另外,我相信这是正确的 可替代性:需要 int 的代码可以输入 bool 它的行为与 0 或 1 相同。需要 给定 int 时,bool 可能不起作用;例如,3 和 4 为 0,但 3 和 4 都为真 价值观。

    另一个不相关的问题是您在迭代列表时正在修改它。阅读Modifying list while iterating 和其中的链接。

    这会导致您的代码中出现一个细微的错误。例如,它无法从以下列表中删除"b"(试试吧!):

    list_a = ["a", "b", 1, 2, 3]
    
    for item in list_a:
        if not isinstance(item, int):
            list_a.remove(item)
    

    解决此问题的一种简洁方法是使用列表推导式。

    【讨论】:

      【解决方案3】:

      不检查一个项目是否是某物的一个实例。直接检查它的类型:

      [x for x in list_a if type(x)==int]
      

      [1, 2, 3]

      【讨论】:

        【解决方案4】:

        一个明确的方法来做到这一点。

        list_a = ["a", 1, 2, 3, False, [1, 2, 3]]
        list_b = []
        for item in list_a:
            if isinstance(item, int) and not isinstance(item, bool):
                list_b.append(item)
        print list_b
        

        输出

        [1, 2, 3]
        

        【讨论】:

          【解决方案5】:

          你在这里犯了两个错误:

          • 假设isinstancebool 一起使用(其他人已经解释了bool 实际上是int 的子类)。
          • 在遍历列表时更改列表

          这可能是需要明确使用type(val) == int 进行测试的情况之一:

          list_a = ["a", 1, 2, 3, False, [1, 2, 3]]
          
          for item in list_a[:]:
              if not type(item) == int:
                  list_a.remove(item)
          

          产生想要的结果;请注意 list_a 是如何与 [:] 复制的,以确保我们迭代其所有内容,尽管从其中删除。

          在理解形式中,这更漂亮:

          res = [i for i in list_a if type(i) == int]
          

          【讨论】:

            【解决方案6】:

            Bool 是 Int 的子类,此外 type() 和 isinstance() 不应混淆。这是因为在 boolean 成为自己的类之前,“1”和“0”分别代表 True 和 False。

            因此,由于继承,您应该使用 type()。

            def f(randomList):
                result = []
                for elem in randomList:
                    if type(elem)==int:
                        result.append(elem)
                return result
            

            这是一个非破坏性修改列表,因为有时修改您正在迭代的列表可能会导致错误或至少是一个痛苦。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-12-26
              • 1970-01-01
              相关资源
              最近更新 更多