【问题标题】:Comparing boolean and int using isinstance使用 isinstance 比较 boolean 和 int
【发布时间】:2016-10-19 16:59:30
【问题描述】:

有人可以解释一下为什么isinstance() 在以下情况下返回 True 吗?在编写代码时,我期望 False。

print isinstance(True, (float, int))
True

我的猜测是它的 Python 内部子类化为零和一(无论是浮点数还是整数)都在用作布尔值时进行评估,但不知道确切的原因。

解决这种情况的最pythonic方法是什么?我可以使用type(),但在大多数情况下,这被认为不那么pythonic。

【问题讨论】:

    标签: python int boolean comparison isinstance


    【解决方案1】:

    由于历史原因,boolint 的子类,所以Trueint 的一个实例。 (最初,Python 没有 bool 类型,返回真值的东西返回 1 或 0。When they added bool,True 和 False 必须尽可能地替换 1 和 0 以实现向后兼容性,因此子类化。 )

    “解决”这个问题的正确方法取决于您认为问题是什么。

    • 如果你想让True 不再是int,那太糟糕了。这不会发生。
    • 如果您想检测布尔值并以不同于其他整数的方式处理它们,您可以这样做:

      if isinstance(whatever, bool):
          # special handling
      elif isinstance(whatever, (float, int)):
          # other handling
      
    • 如果你想检测特定类正好是floatint的对象,拒绝子类,你可以这样做:

      if type(whatever) in (float, int):
          # Do stuff.
      
    • 如果您想检测所有浮点数和整数,您已经在这样做了。

    【讨论】:

    • 是第二种情况。这意味着必须注意这些内置类型的比较顺序 - 考虑到继承,这是可以理解的,但对于 python 来说却很不寻常。
    • 更深层次的解释: TrueFalseint 类的单例实例... print(True.real)1,而 print(False.real)0print(True == 1) 为真,print(False == 0) 为真。因此,如果您希望参数是 int,而用户传递的是 bool,那么是的,isinstance(param, int) 检查对于他们传递的值将“烦人”为真,因为 bool 是 int ......但是这有点无害,因为就好像他们通过了param = 1param = 0。所以你仍然可以对其进行数字运算,因为布尔值在内部是 int
    • 更深入的解释第 2 部分: 你甚至可以做 print(True + 3)4 (1 + 3) 和 print(False + 3)3 (0 + 3)。呵呵。但如上面的答案所述,如果您想 100% 确定他们通过了 int 而不是 bool,您只需检查 if type(param) is int,因为它不会接受任何子类。 (如果您的 API 用户可能将他们自己的从 int 派生的自定义对象作为基类传递,请小心,例如,如果他们创建一个带有一些额外方法的 int 数字类......因为他们的子类也会被这么严格的检查拒之门外……)
    【解决方案2】:

    是的,没错,它是int的子类,你可以使用解释器来验证:

    >>> int.__subclasses__()
    [<type 'bool'>]
    

    【讨论】:

      【解决方案3】:

      如果你只想检查int

      if type(some_var) is int:
          return True
      
      else:
          return False
      

      【讨论】:

      • 更简单:return type(some_var) is int
      【解决方案4】:

      您可以看到方法解析顺序,并从那里找到所有超类:

      >>> bool.__mro__
      (<class 'bool'>, <class 'int'>, <class 'object'>)
      

      【讨论】:

        【解决方案5】:

        在 bool 和 int 上查看 python 的一些行为(不是那么奇怪)

        >>> 1 == True  
        True           
        >>> 0 == False 
        True           
        >>> True*5 == 0
        False          
        >>> True*5 == 5
        True           
        >>> 
        

        它们可以如何互换使用...!

        从 boolobject.h (win py 2.7) 我可以看到 bool obj 的类型定义为 int。所以很明显 bool 继承了 int 的一些面部特征。

        #ifndef Py_BOOLOBJECT_H
        #define Py_BOOLOBJECT_H
        #ifdef __cplusplus
        extern "C" {
        #endif
        
        
        typedef PyIntObject PyBoolObject;
        

        【讨论】:

          【解决方案6】:

          这是一个实例检查器,它使用 bool 是安全的,并采用单一类型或类型元组,就像 isinstance()

          def isInst(o, of) -> bool:
              if o is None: return False
              cls = o.__class__
              if isinstance(of, type):
                  return cls == of
          
              else:
                  if cls == bool:
                      return bool in of
                  else:
                      for i in range(len(of)):
                          if cls == of[i]: return True
          
              return False
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-24
            • 1970-01-01
            • 2021-05-19
            相关资源
            最近更新 更多