11
'2'<'1'== False #False
('2'<'1')== False #True
'2'<('1'== False) #error

code in python3 we know operator precedence in python3 https://docs.python.org/3/reference/expressions.html#operator-precedence

wzf wu
  • 126
  • 4

3 Answers3

15

In case 1 :-

'2'<'1'== False

it is evaluated as '2'<'1' and '1' == False according to the operator chaining {thanks @ymonad to provide this link}

which will evaluated to be False

in case 2 :-

('2'<'1')== False

as () have higher precedence so will be evaluated first. so the expression will be reduced to False == False which will evaluate to be True

in case 3 :-

'2'<('1'== False)

first ('1' == False) is evaluated which is False but now the operation is '2'<False which is an illegal operation in python


EDIT:

To answer a question raised by @snr in the comment section

The vital question is why '1'== False is valid while '2'< bool is not

It is because the default behaviour for equality comparison (== and !=) is based on the identity of the objects, and as object False and object '1' does not share the same identity thus the result will be False

whereas a default behaviour of other comparison (<, >, <=, and >=) is not provided thus an attempt to do so raises TypeError


you can find this in documentation link provided by OP (under the heading value-comparisions)

Arsenic
  • 702
  • 1
  • 6
  • 20
  • 2
    Good answer, but who on earth thought it was a good idea for `a – Everyone Nov 05 '20 at 06:37
  • 2
    @Everyone that's true, this doesn't happen in other languages like C/C++ where we have different precedence for comparison operators. – Arsenic Nov 05 '20 at 06:41
  • 1
    I am not aware of any other language, or any other logic operations procedure, that would make such interpretation. A program should only do what you tell it to do. We usually say this statement to people who think their programs should behave like they wish, not what they told the programs to do. Yet here, it seems the program is doing what it wishes of its own, not what you told it to do. I am once again reminded why I keep getting away from this language every time I come back. – Everyone Nov 05 '20 at 06:43
  • 2
    Just for (maybe?) completeness, `'2' – Everyone Nov 05 '20 at 06:45
  • 3
    @Everyone, it all starts with a good intent, `3 < blah < 4` is equivalent to `3 < blah and blah < 4` with `blah` evaluated only once. You may be used to the C like syntax but I find this more intuitive for beginners. This syntax may be misleading though: `==` is also a comparison operator and can therefore be chained with other comparison operators like in the OP's example, producing counter intuitive expressions. – vc 74 Nov 05 '20 at 08:59
  • 2
    The vital question is why **'1'== False** is valid while **'2'< bool** is not. That's why I didn't answer the question simply. – snr Nov 05 '20 at 09:07
  • @snr that's a nice question. I have answered it in the edited part of the post – Arsenic Nov 05 '20 at 11:17
  • @Arsenic False and object '1' does not share the same identity ?? If IT DOESN'T share what about '2'< bool value ? Did you miswrite? Even if so, could you explain both cases ? – snr Nov 05 '20 at 12:52
  • @snr it's only equality/inequality operator whose default behaviour is to check for object identity if value comparison fails. there is not such rule for other comparison operators thus it don't know what to do if objects of different types are received. look at the documentation link provided at the end of answer to get a better picture of it. – Arsenic Nov 05 '20 at 16:03
  • (: It means I don’t know what s going on under the Iceberg. Thanks for the answer. – snr Nov 05 '20 at 17:24
0

When python tries to do string < string then it turns into ascii and it orders it by alphabet order. https://careerkarma.com/blog/python-compare-strings/

By the way, 1 ascii is 49 and 2 ascii is 50

First case

'2'<'1'== False #False

it is evaluated as '2'<'1' and '1' == False which is False
because 50 < 49 and 1 == False -> False and False -> False

second case

('2'<'1')== False # True

it makes python do () first. (50 < 49) == False-> False == False -> True

third case

'2'<('1'== False) #error 

first ('1' == False) is evaluated which is False and you try to do '2'<False. And it get's an error.

Python Operator Precedence: https://www.mathcs.emory.edu/~valerie/courses/fall10/155/resources/op_precedence.html

David Hammen
  • 31,392
  • 8
  • 57
  • 102
ppwater
  • 2,304
  • 4
  • 14
  • 29
-2

I really tried to dig into but I can't get an answer which satisfies me. However, a person who has some time can walk through the following.

PyObject *tp_richcompare(PyObject *self, PyObject *other, int op); methods runs under the hood. Its implementation is here.

As far as I understand, it firstly checks whether both PyObjects are comperable by inspecting the object types by e.g.

(!Py_IS_TYPE(v, Py_TYPE(w)) &&
 PyType_IsSubtype(Py_TYPE(w), Py_TYPE(v)) &&
 (f = Py_TYPE(w)->tp_richcompare) != NULL)  

As we can see also in your code, while <class 'str'> __eq__ <class 'int'> is meant to 'Yes, they are compatible with each other w.r.t. the comparison.', <class 'str'> __lt__ <class 'bool'> is the opposite. We are pretty sure that one of the last stations is here.

print(type(1))
print(type('1'))
print(type(False))
print(type('1' == 1))
print('1' == 1) #False <class 'str'> __eq__ <class 'int'>
print(('2' < '1')== False) #True
#print('2'<('1'== False))  <class 'str'> __lt__ (<class 'str'> __eq__ <class 'bool'>)
# (<class 'str'> __eq__ <class 'bool'>) returns <class 'bool'>, then as a result
# <class 'str'> __lt__  <class 'bool'> comparison is not implemented.

As a side note, its satisfactory answer, at least for me, must include detailed C explanations, not Pythonic

snr
  • 16,197
  • 2
  • 61
  • 88