一尘不染

在Python中编写双重不等式时,运算符的优先级是什么(在代码中明确地说明了这一点,以及如何将其重写为数组?)

python

当我要求类似的东西时,要执行的具体代码是什么

>>> 1 <= 3 >= 2
True

如果两者具有相同的优先级,并且只是它们的求值顺序,那么为什么第二个不等式起(3 >= 2)代替(True >= 2)

考虑例如这些之间的区别

>>> (1 < 3) < 2
True

>>> 1 < 3 < 2
False

仅仅是and将两个语句中的第二个扩展为Python的纯粹的语法快捷方式硬编码到Python中吗?

我可以为一个类更改此行为,以使其a <= b <= c扩展到其他内容吗?看起来是这样

a (logical operator) b (logical operator) c 
    --> (a logical operator b) and (b logical operator c)

但是真正的问题是如何在代码中实现它。

我很好奇,这样我可以复制这种__lt____gt__行为在一些我自己的类,但我感到困惑,这是如何实现的固定中部参数不变。

这是一个具体的例子:

>>> import numpy as np

>>> tst = np.asarray([1,2,3,4,5,6])

>>> 3 <= tst
array([False, False,  True,  True,  True,  True], dtype=bool)

>>> 3 <= tst <= 5
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/home/ely/<ipython-input-135-ac909818f2b1> in <module>()
----> 1 3 <= tst <= 5

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

最好重写它,以便它也“适用于”数组,如下所示:

>>> np.logical_and(3 <= tst, tst <= 5)
array([False, False,  True,  True,  True,  False], dtype=bool)

添加以澄清

评论中指出,我在解释这个问题上做得很差。以下是一些澄清的说明:

1)我 不是要 寻找一个简单的解释,即口译员会and在两个连锁不平等之间夹杂一个事实。我已经知道这一点,并在上面这么说。

2)与我想做的事情类似,请考虑以下with语句(link)。以下:

with MyClass(some_obj) as foo:
    do_stuff()

打开包装

foo = MyClass(some_obj)
foo.__enter__()
try:
    do_stuff()
finally:
    foo.__exit__()

因此,通过MyClass适当地编写,我可以在with语句内部做很多特殊的事情。

我在问是否存在类似的链式不平等解包代码,通过它我可以截取它的工作并将其重定向为使用数组样式的逻辑运算符,而 不仅仅是我关心的类

我觉得从我的问题(尤其是示例)中可以很清楚地看出这一点,但希望这可以使它更加清楚。


阅读 294

收藏
2021-01-20

共1个答案

一尘不染

我不确定您要寻找的是什么,但是快速反汇编显示a < b < c未编译为与a < b and b < c

>>> import dis
>>>
>>> def f(a, b, c):
...     return a < b < c
...
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 DUP_TOP
              7 ROT_THREE
              8 COMPARE_OP               0 (<)
             11 JUMP_IF_FALSE_OR_POP    21
             14 LOAD_FAST                2 (c)
             17 COMPARE_OP               0 (<)
             20 RETURN_VALUE
        >>   21 ROT_TWO
             22 POP_TOP
             23 RETURN_VALUE
>>>
>>> def f(a, b, c):
...     return a < b and b < c
...
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                1 (b)
              6 COMPARE_OP               0 (<)
              9 JUMP_IF_FALSE_OR_POP    21
             12 LOAD_FAST                1 (b)
             15 LOAD_FAST                2 (c)
             18 COMPARE_OP               0 (<)
        >>   21 RETURN_VALUE

编辑1: 进一步挖掘,我认为这与numpy有点奇怪或错误。考虑这个示例代码,我认为它可以按您期望的那样工作。

class Object(object):
    def __init__(self, values):
        self.values = values
    def __lt__(self, other):
        return [x < other for x in self.values]
    def __gt__(self, other):
        return [x > other for x in self.values]

x = Object([1, 2, 3])
print x < 5 # [True, True, True]
print x > 5 # [False, False, False]
print 0 < x < 5 # [True, True, True]

编辑2: 实际上,这不能“正确地”工作…

print 1 < x # [False, True, True]
print x < 3 # [True, True, False]
print 1 < x < 3 # [True, True, False]

我认为它是在的第二次比较中将布尔值与数字进行比较1 < x < 3

编辑3: 我不喜欢从gt,lt,gte,lte特殊方法返回非布尔值的想法,但是根据Python文档,它实际上不受限制。

http://docs.python.org/reference/datamodel.html#object。
lt

按照惯例,返回False和True进行成功比较。但是,这些方法可以返回任何值…

2021-01-20