파이썬에서 표현식 0 <0 == 0이 False를 반환하는 이유는 무엇입니까?
Python 2.6에서 Queue.py를 살펴보면이 구성이 조금 이상하다는 것을 알았습니다.
def full(self):
"""Return True if the queue is full, False otherwise
(not reliable!)."""
self.mutex.acquire()
n = 0 < self.maxsize == self._qsize()
self.mutex.release()
return n
경우 maxsize
0 큐는 결코 가득 차있다.
내 질문은이 경우 어떻게 작동합니까? 0 < 0 == 0
거짓으로 어떻게 간주됩니까?
>>> 0 < 0 == 0
False
>>> (0) < (0 == 0)
True
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
파이썬에는 범위 비교를 쉽게 표현할 수 있도록 일련의 관계 연산자에 대한 특별한 경우 처리 기능이 있다고 생각합니다. 말하는 0 < x <= 5
것보다 말할 수있는 것이 훨씬 좋습니다 (0 < x) and (x <= 5)
.
이를 체인 비교 라고 합니다. 그리고 그것은 그것들을위한 문서에 대한 링크입니다.
다른 경우에 대해서는, 괄호는 한 관계 연산자가 다른 관계 연산자보다 먼저 적용되도록하므로 더 이상 연쇄 비교되지 않습니다. 그리고 이후 True
및 False
정수로 값을 당신은 괄호 버전 밖으로 수행 답변을 얻을.
때문에
(0 < 0) and (0 == 0)
입니다 False
. 비교 연산자를 함께 연결할 수 있으며 쌍 연산자로 자동 확장됩니다.
편집-파이썬에서 참과 거짓에 대한 설명
파이썬에서 True
와 False
단지 인스턴스 bool
의 서브 클래스입니다 int
. 다시 말해, True
실제로는 1입니다.
요점은 정수와 똑같이 부울 비교 결과를 사용할 수 있다는 것입니다. 이것은 다음과 같은 혼란을 초래합니다
>>> (1==1)+(1==1)
2
>>> (2<1)<1
True
그러나 이러한 평가는 비교를 괄호로 묶어 먼저 평가되도록하는 경우에만 발생합니다. 그렇지 않으면 파이썬은 비교 연산자를 확장합니다.
이상한 행동은 파이썬이 조건을 연쇄시키는 능력에서 비롯됩니다. 0이 0보다 작지 않다는 것을 알기 때문에 전체 표현식이 false로 평가됩니다. 이를 별도의 조건으로 나누 자마자 기능이 변경됩니다. 처음 a < b && b == c
에의 원래 진술 을 위해 기본적으로 테스트하고 있습니다 a < b == c
.
다른 예시:
>>> 1 < 5 < 3
False
>>> (1 < 5) < 3
True
>>> 0 < 0 == 0
False
이것은 체인 비교입니다. 각 쌍별 비교가 차례로 참이면 true를 리턴합니다. 그것은(0 < 0) and (0 == 0)
>>> (0) < (0 == 0)
True
이것은 0 < True
True로 평가되는 것과 같습니다 .
>>> (0 < 0) == 0
True
이것은 False == 0
True로 평가되는 것과 같습니다 .
>>> 0 < (0 == 0)
True
0 < True
위와 같이 True로 평가되는 것과 같습니다 .
Looking at the disassembly (the bytes codes) it is obvious why 0 < 0 == 0
is False
.
Here is an analysis of this expression:
>>>import dis
>>>def f():
... 0 < 0 == 0
>>>dis.dis(f)
2 0 LOAD_CONST 1 (0)
3 LOAD_CONST 1 (0)
6 DUP_TOP
7 ROT_THREE
8 COMPARE_OP 0 (<)
11 JUMP_IF_FALSE_OR_POP 23
14 LOAD_CONST 1 (0)
17 COMPARE_OP 2 (==)
20 JUMP_FORWARD 2 (to 25)
>> 23 ROT_TWO
24 POP_TOP
>> 25 POP_TOP
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
Notice lines 0-8: These lines check if 0 < 0
which obviously returns False
onto the python stack.
Now notice line 11: JUMP_IF_FALSE_OR_POP 23
This means that if 0 < 0
returns False
perform a jump to line 23.
Now, 0 < 0
is False
, so the jump is taken, which leaves the stack with a False
which is the return value for the whole expression 0 < 0 == 0
, even though the == 0
part isn't even checked.
So, to conclude, the answer is like said in other answers to this question. 0 < 0 == 0
has a special meaning. The compiler evaluates this to two terms: 0 < 0
and 0 == 0
. As with any complex boolean expressions with and
between them, if the first fails then the second one isn't even checked.
Hopes this enlightens things up a bit, and I really hope that the method I used to analyse this unexpected behavior will encourage others to try the same in the future.
As other's mentioned x comparison_operator y comparison_operator z
is syntactical sugar for (x comparison_operator y) and (y comparison_operator z)
with the bonus that y is only evaluated once.
So your expression 0 < 0 == 0
is really (0 < 0) and (0 == 0)
, which evaluates to False and True
which is just False
.
maybe this excerpt from the docs can help:
These are the so-called “rich comparison” methods, and are called for comparison operators in preference to
__cmp__()
below. The correspondence between operator symbols and method names is as follows:x<y
callsx.__lt__(y)
,x<=y
callsx.__le__(y)
,x==y
callsx.__eq__(y)
,x!=y
andx<>y
callx.__ne__(y)
,x>y
callsx.__gt__(y)
, andx>=y
callsx.__ge__(y)
.A rich comparison method may return the singleton
NotImplemented
if it does not implement the operation for a given pair of arguments. By convention,False
andTrue
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 callbool()
on the value to determine if the result is true or false.There are no implied relationships among the comparison operators. The truth of
x==y
does not imply thatx!=y
is false. Accordingly, when defining__eq__()
, one should also define__ne__()
so that the operators will behave as expected. See the paragraph on__hash__()
for some important notes on creating hashable objects which support custom comparison operations and are usable as dictionary keys.There are no swapped-argument versions of these methods (to be used when the left argument does not support the operation but the right argument does); rather,
__lt__()
and__gt__()
are each other’s reflection,__le__()
and__ge__()
are each other’s reflection, and__eq__()
and__ne__()
are their own reflection.Arguments to rich comparison methods are never coerced.
These were comparisons but since you are chaining comparisons you should know that:
Comparisons can be chained arbitrarily, e.g.,
x < y <= z
is equivalent tox < y and y <= z
, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).Formally, if a, b, c, ..., y, z are expressions and op1, op2, ..., opN are comparison operators, then a op1 b op2 c ... y opN z is equivalent to a op1 b and b op2 c and ... y opN z, except that each expression is evaluated at most once.
Here it is, in all its glory.
>>> class showme(object):
... def __init__(self, name, value):
... self.name, self.value = name, value
... def __repr__(self):
... return "<showme %s:%s>" % (self.name, self.value)
... def __cmp__(self, other):
... print "cmp(%r, %r)" % (self, other)
... if type(other) == showme:
... return cmp(self.value, other.value)
... else:
... return cmp(self.value, other)
...
>>> showme(1,0) < showme(2,0) == showme(3,0)
cmp(<showme 1:0>, <showme 2:0>)
False
>>> (showme(1,0) < showme(2,0)) == showme(3,0)
cmp(<showme 1:0>, <showme 2:0>)
cmp(<showme 3:0>, False)
True
>>> showme(1,0) < (showme(2,0) == showme(3,0))
cmp(<showme 2:0>, <showme 3:0>)
cmp(<showme 1:0>, True)
True
>>>
I'm thinking Python is doing it's weird between magic. Same as 1 < 2 < 3
means 2 is between 1 and 3.
In this case, I think it's doing [middle 0] is greater than [left 0] and equal to [right 0]. Middle 0 is not greater than left 0, so it evaluates to false.
참고URL : https://stackoverflow.com/questions/6074018/why-does-the-expression-0-0-0-return-false-in-python
'IT' 카테고리의 다른 글
다른 디렉토리에서 git clone (0) | 2020.06.28 |
---|---|
ES6 / 2015의 안전하지 않은 속성 액세스 및 조건부 할당 (0) | 2020.06.28 |
Github 개인 저장소를위한 Jenkins CI 인증 (0) | 2020.06.28 |
모듈에 중첩 된 클래스와 중첩 클래스를 사용하는시기 (0) | 2020.06.28 |
Java 8-Optional.flatmap과 Optional.map의 차이점 (0) | 2020.06.28 |