Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusing about a Python min quiz

Tags:

python

Just now I saw a quiz on this page:

>>> x, y = ???
>>> min(x, y) == min(y, x)
False

The example answer is

x, y = {0}, {1}

From the documentation I know that:

min(iterable[, key=func]) -> value
min(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its smallest item.
With two or more arguments, return the smallest argument.

But why is min({0},{1})={0} and min({1},{0})={1}?

I also tried a few others:

min({0,2},1)   # 1
min(1,{0,2})   # 1
min({1},[2,3]) # [2,3]
min([2,3],1)   # 1
like image 945
Hongxu Chen Avatar asked Oct 10 '15 01:10

Hongxu Chen


3 Answers

The comparison operators <, <=, >=, and > check whether one set is a strict subset, subset, superset, or strict superset of another, respectively.

{0} and {1} are False for all of these, so the result depends on the check order and operator.

like image 156
Ry- Avatar answered Nov 06 '22 07:11

Ry-


The key point here is, the two sets are not subsets of each other, so both are False for < even though they are not equal:

>>> {0} < {1}
False
>>> {0} > {1}
False
>>> {0} == {1}
False

So which one is smaller? The fact that sets don't provide strict weak ordering means there's no correct answer.

like image 8
Yu Hao Avatar answered Nov 06 '22 08:11

Yu Hao


min is implemented roughly like this:

def min(*args):
    least = args[0]
    for arg in args:
        if arg < least:
            least = arg
    return least

The way the comparison operators work for sets break one of the assumptions that this implicitly makes: that for every pair of objects, either they are equal, or a < b or b < a. Neither {0} nor {1} compare less than one another, so min gives you inconsistent answers.

The other results you see are because of the rules for how Python defines an order for mixed types. A set and an int aren't comparable - neither of those types defines a rule for comparing to the other. This leads Python 2 to apply a rule called "arbitrary but consistent order" - one of the types is chosen to be the "lower" type, and it will remain the lower type for the lifetime of the program. In practice, it will be the same across all code you run, because it is implemented by comparing the type names alphabetically - but in theory, that could change.

The "arbitrary but consistent order" rule has been dumped from Python 3, because the only effect it really had was to mask bugs. When there is no defined rule for finding an order, Python now tells you so:

>>> 1 < {0}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < set()
like image 7
lvc Avatar answered Nov 06 '22 07:11

lvc