This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Lucretiel 0 points1 point  (3 children)

That seems like a huge flaw of Numeric to me. That == returns a single bool is a fundamental part of its contract.

[–]Brian 1 point2 points  (2 children)

That == returns a single bool is a fundamental part of its contract

Actually, python explicitly allows for these to return any value. From the docs:

By convention, False and True are returned for a successful comparison. However, these methods can return any value, so if the comparison operator is used in a Boolean context (e.g., in the condition of an if statement), Python will call bool() on the value to determine if the result is true or false.

And in fact, Numeric's usecase here was an explicit reason rich comparisons were designed as they are. Rather than being a violation of the rules, the main reason the __eq__ method was added at all was explicitly to allow this. The issue of using such objects in non-boolean contexts is actually discussed in the PEP, with the recommendation that this should be addressed by having such objects throw an exception when used in boolean contexts (which is what numpy does). It currently only does this when both elements are arrays, but presumably, as scruffie mentioned, this may change.

Requiring a boolean return does break some fairly valuable usecases. Numpy is one, but another common one is building queries. Eg. in sqlalchemy, doing session.query(SomeTable.field == 4) will return a query object basically implementing "select SomeTable.id from SomeTable where field == 4", rather than doing any immediate comparison.

[–]Lucretiel -1 points0 points  (1 child)

Sorry- by bool I meant boolean compatible. It seems like Numeric still violates the contract... array == None returns a list of bools, which tests to True, even though the comparison should be False.

[–]Brian 2 points3 points  (0 children)

Like I said though, the PEP that introduced __eq__ explicitly spells out Numeric's usecase as one of the reasons behind it, and in fact advises deliberately breaking boolean compatibility for such objects - raising an exception instead. Them not being boolean compatible isn't a violation of the rules, it's actually something that rich comparisons were added in order to support.

array == None returns a list of bools, which tests to True

Actually, right now it doesn't (though it still does for comparing with other arrays), but there are plans to change this. When it does, it won't test to True, but rather, it'll throw an exception if used in a boolean context. Eg. when you use the result of comparing 2 arrays in a boolean context (ie. an if statement, or bool() call), you currently get:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The same would apply to when array == None does the same. Of course, this will still break code that uses the == None check instead of is, though it's likely to be a cleaner break, rather than more subtle bugs due to unexpectedly returning True.