【问题标题】:Strict comparison严格比较
【发布时间】:2015-01-19 21:34:22
【问题描述】:

在 javascript 中,有严格的比较运算符 op1 === op2op1 !== op2 将比较类型和值。有没有实现同样事情的pythonic方法?

到目前为止,我只能想出以下杂乱无章的条件:

isinstance(op1, type(op2)) and isinstance(op2, type(op1)) and op1 == op2

not isinstance(op1, type(op2)) or not isinstance(op2, type(op1)) or op1 != op2

【问题讨论】:

  • 不,没有,您只能测试身份is(引用同一个对象)或相等==(依赖于__eq__魔术方法的实现)。
  • @jonrsharpe 如果您使用的是!=,请不要忘记神奇的__ne__ 方法。

标签: python python-3.x


【解决方案1】:

Python 的相等比较器是严格的,除了将 1 与 True 以及 0 与 False 进行比较时,1 或 0 的值是 float、decimal.Decimal 还是 long 类型都没有关系。任何数字类型的零(例如 0、0L、0.0、0j)始终为 False。 (请注意,转换为布尔值的任何其他内容都是 True。请参阅 Truth Value Testing in Python。)除复数 (1L, 1.0, 1) 之外的任何类型的 1 始终为 True。

在 Python 中:

0 == '0'  # False
0 == '0' and type(0) == type('0')  # False, compare short circuits 
0 == ''  # False
0 == '' and type(0) == type('')  # False, compare short circuits 

1 == True and type(1) == type(True)  # False, makes a difference here
1 == True  # True, also true if 1 was 1.00, etc..
0 == False  # True
False == None  # False
0 == bool(None)  # True

当第一个比较返回 False 时,第二个比较不会被评估,因此它会短路,因为 0 和其他任何东西都是 0。但这不是必需的,它只适用于第 6 行中将 1 与 True 进行比较时。

在 JavaScript 中:

0 == '0'  //true
0 === '0'  //false
0 == ''  //true
0 === '0' //false

1 === true //false
1 == true //true
0 == false //true
false == null //false
0 == !!(null) //true

所以最接近 Python 中的 JavaScript === 的是:

a == b and type(a) == type(b)

但只有在与 1 或 0 进行布尔比较的情况下才需要使用,这不太可能。如果您希望一个值是数字或布尔值,您可能需要修复您的代码。一个菜鸟的错误就是发生这样的事情:

a = 0.0  # a valid value, lets assume it comes from a source that can also return None and we have no control over that.

# Should be:
# if a not None:
if a: # a is cast to bool, bool(0.0) is False
    print "do something here..."

为了澄清一些困惑,了解 Python 的 is 运算符是一件好事。 Python 有一个 is 运算符,如果 is 的两边都绑定到同一个对象,则返回 True,否则返回 False。使用字符串文字时,对象的生命周期仅针对语句的实例。因此,对字符串字面量执行 is 是安全的,因为如果它们相同,它们将被分配给同一个对象。这也适用于其他不可变类型,如 bool 和所有数字类型:

0 is '0'  # False
0 is False  # False
0 is 0  # True

当比较两个变量或一个变量和一个文字时,这不能保证有效。

当您创建两个空列表时,您会得到两个不同的对象,因此返回 False:

x = []
y = []
x is y  # False

但在这种情况下,这些变量引用同一个列表,并将继续这样做,直到它们被重新分配,或者从另一个中复制一个深拷贝:

x = y = []
x is y  # True
x.append(1)
x is y  # True
x = [1, ]
x is y  # False, even though the value is same

is 运算符正在比较对象的身份,它执行以下操作:

id('0') == id(0)

因此,如果两个对象都引用相同的内存,那么它们引用的是相同的对象,因此必须相同。

最好避免 is 进行严格比较,除非您想检查两个对象是否引用相同的内存。

正如 Simon 的回答所说,Python 的平等哲学与 JavaScript 不同,确实不需要严格的平等比较器。 Python 的相等比较器不像 JavaScripts == 那样松散,但同时它与 === 不完全相同。

只要你清楚任何数字类型的零(0、0L、0.0、0j)总是等于 False 和任何数字类型的 1,除了复数(1, 1L, 1.0) 为真。

【讨论】:

  • == 仅对内置对象严格 - 在自定义类上,它可以按照设计者的意愿定义为非严格 - 因为您可能不需要严格比较 - 这取决于您的语义希望你的课有。此外 - 如果您正在比较对象实例 - 使用 is 而不是比较 ids 不是更好吗?
【解决方案2】:

您的方法确实会检查值和类型。 Python 中没有不同的运算符。

话虽如此,在很多情况下这并不是你想要的——在 Python 的哲学中,任何表现得像鸭子的对象都应该被视为鸭子。您通常不仅需要字典,还需要“类似映射”的对象等等——只要该对象可以用于特定任务,那么代码就应该接受它。

【讨论】:

    【解决方案3】:

    Python 的相等比较器在大多数情况下总是严格的。

    例如:

    Python

    0 == '0'  # False
    0 == ''  # False
    

    Javascript

    0 == '0'  //True
    0 === '0'  //False
    0 == ''  //True
    0 === '0' //False
    

    【讨论】:

    • 我需要担心的情​​况经常涉及布尔类型:1 == True #True 而在 javascript 中 1 === true //false
    • @RPGillespie 您始终可以使用 is 运算符来表示 True 和 False。 1 is True # False(1 == 1) is True #True(1 == 'a') is False #True, (1 == 'a') is (3 == 1) #True.
    • @RPGillespie 在什么情况下您将数字与真/假进行比较?也许你有一个潜在的逻辑错误,最好改正一下。
    • @MarkRansom 我正在比较两个导入的 JSON 对象的字段,我想打印出类型或值不同的字段。
    • @RPGillespie 那么我猜你被卡住了,Python 认为布尔值是整数的子类; isinstance(False,int) 返回True
    【解决方案4】:

    如果你想超级严格,你也可以使用 operator 模块。 https://docs.python.org/2/library/operator.html

    >>> import operator
    >>> operator.eq(True, 1)
    True
    >>> operator.is_(True, 1)
    False
    

    这里的一些答案是错误的。例如,Python 不会区分某些类型,以便进行一些比较。

    例如:

    >>> 1 == 1.0
    True
    >>> operator.eq(1, 1.0)
    True
    >>> operator.is_(1, 1.0)
    False
    

    Is 比 eq(或 ==)效果更好,但它依赖于指向相同值的变量,这意味着有很多情况你不喜欢。

    如果您想深入了解,以简写方式实现它,如下所示:http://code.activestate.com/recipes/384122/ 将让您“有点”构建自己的运算符。

    【讨论】:

    • 您的示例与==is 相同。只会更容易使用is1 is 1.0 # False。 operator 模块只是功能相同的东西。
    【解决方案5】:

    在python中只有一个严格的比较运算符是== 假设我们有两种情况:

    >>> 2 == '2'
    False
    
    # Comparison of Int with string, it returns False
    
    >>> 2 == 2.0
    True
    
    # Comparison of Int with Float, it returns True
    

    但是在 Julia 等其他编程语言中,比较运算符和严格比较运算符是有区别的。

    >>> 2 == 2.0
    true
    
    >>> 2 === 2.0
    false
    
    # strict comparison operator, namely === which is true only if two values agree fully as to type as well as value.
    

    【讨论】:

      猜你喜欢
      • 2012-02-22
      • 1970-01-01
      • 2013-07-20
      • 2017-09-21
      • 1970-01-01
      • 2018-02-03
      • 1970-01-01
      • 2013-05-10
      • 2010-10-09
      相关资源
      最近更新 更多