如果您在 Python 3.7 中执行以下语句,它将(根据我的测试)打印 b:
If you execute the following statement in Python 3.7, it will (from my testing) print b:
if None.__eq__("a"): print("b")但是,None.__eq__("a") 的计算结果为 NotImplemented.
However, None.__eq__("a") evaluates to NotImplemented.
自然,"a".__eq__("a") 的计算结果为 True,而 "b".__eq__("a")> 计算结果为 False.
Naturally, "a".__eq__("a") evaluates to True, and "b".__eq__("a") evaluates to False.
我最初在测试函数的返回值时发现了这一点,但在第二种情况下没有返回任何内容——因此,该函数返回了 None.
I initially discovered this when testing the return value of a function, but didn't return anything in the second case -- so, the function returned None.
这是怎么回事?
推荐答案这是一个很好的例子,说明为什么 __dunder__ 方法不应该直接使用,因为它们通常不适合替代它们的等效方法运营商;您应该使用 == 运算符代替相等比较,或者在这种特殊情况下,在检查 None 时,使用 is(跳到答案底部以获取更多信息).
This is a great example of why the __dunder__ methods should not be used directly as they are quite often not appropriate replacements for their equivalent operators; you should use the == operator instead for equality comparisons, or in this special case, when checking for None, use is (skip to the bottom of the answer for more information).
你已经完成了
None.__eq__('a') # NotImplemented返回 NotImplemented 因为被比较的类型不同.考虑另一个示例,其中以这种方式比较具有不同类型的两个对象,例如 1 和 'a'.做 (1).__eq__('a') 也是不正确的,会返回 NotImplemented.比较这两个值是否相等的正确方法是
Which returns NotImplemented since the types being compared are different. Consider another example where two objects with different types are being compared in this fashion, such as 1 and 'a'. Doing (1).__eq__('a') is also not correct, and will return NotImplemented. The right way to compare these two values for equality would be
1 == 'a' # False这里发生了什么
这是一个不错的小 MCVE,使用一些自定义类来说明这是如何发生的:
Here's a nice little MCVE using some custom classes to illustrate how this happens:
class A: def __eq__(self, other): print('A.__eq__') return NotImplemented class B: def __eq__(self, other): print('B.__eq__') return NotImplemented class C: def __eq__(self, other): print('C.__eq__') return True a = A() b = B() c = C() print(a == b) # A.__eq__ # B.__eq__ # False print(a == c) # A.__eq__ # C.__eq__ # True print(c == a) # C.__eq__ # True当然,这并不能解释为什么操作返回 true.这是因为 NotImplemented 实际上是一个真值:
Of course, that doesn't explain why the operation returns true. This is because NotImplemented is actually a truthy value:
bool(None.__eq__("a")) # True同,
bool(NotImplemented) # True有关哪些值被视为真值和假值的更多信息,请参阅 真值测试,以及这个答案.这里值得注意的是 NotImplemented 是真实的,但如果该类定义了一个 __bool__ 或 __len__ 方法返回False 或 0 分别.
For more information on what values are considered truthy and falsy, see the docs section on Truth Value Testing, as well as this answer. It is worth noting here that NotImplemented is truthy, but it would have been a different story had the class defined a __bool__ or __len__ method that returned False or 0 respectively.
如果您需要 == 运算符的等效功能,请使用 operator.eq:
If you want the functional equivalent of the == operator, use operator.eq:
import operator operator.eq(1, 'a') # False但是,如前所述,对于这个特定场景,您正在检查None,请使用is:
However, as mentioned earlier, for this specific scenario, where you are checking for None, use is:
var = 'a' var is None # False var2 = None var2 is None # True与此等效的功能是使用 operator.is_:
The functional equivalent of this is using operator.is_:
operator.is_(var2, None) # TrueNone 是一个特殊的对象,在任何时候内存中都只存在一个版本.IOW,它是 NoneType 类的唯一单例(但同一个对象可能有任意数量的引用).PEP8 指南 明确指出:
None is a special object, and only 1 version exists in memory at any point of time. IOW, it is the sole singleton of the NoneType class (but the same object may have any number of references). The PEP8 guidelines make this explicit:
与 None 之类的单例比较应该始终使用 is 或不是,永远不是等号运算符.
Comparisons to singletons like None should always be done with is or is not, never the equality operators.
总而言之,对于像 None 这样的单例,使用 is 进行引用检查更合适,尽管 == 和 都是 会工作得很好.
In summary, for singletons like None, a reference check with is is more appropriate, although both == and is will work just fine.
更多推荐
为什么 `if None.
发布评论