Python`或`,`和`运算符优先级示例

Wlo*_*oHu 3 python boolean-logic operator-precedence short-circuiting

我无法在Python中生成示例,其中显示了布尔运算符优先级规则以及短路评估.我可以用以下方式显示运算符优先级

print(1 or 0 and 0)  # Returns 1 because `or` is evaluated 2nd.
Run Code Online (Sandbox Code Playgroud)

但是当我将其更改为此时,出现短路问题:

def yay(): print('yay'); return True
def nay(): print('nay')
def nope(): print('nope')
print(yay() or nay() and nope())  # Prints "yay\nTrue"
Run Code Online (Sandbox Code Playgroud)

对于每一个的4种可能性时表达式之前orTrue它是唯一的求值表达式.如果运算符优先级有效,则应打印"nay\nnope\nyay\nTrue""nay\nyay\nTrue"短路,因为and应该首先进行评估.

从这个例子中可以想到的是,Python从左到右读取布尔表达式,并在结果已知时结束,无论运算符优先级如何.

我的错误在哪里或者我错过了什么?请举例说明and第一次评估它是否可见,这不是由于代码从左到右解释.

tob*_*s_k 6

您将操作员优先级和评估顺序混淆.

表达式r = x or y and z不作为评估tmp = y and z; r = x or tmp,而是评估为r = x or (y and z).此表达式从左到右进行计算,如果or已经确定了结果,则(y and z)根本不进行评估.

请注意,这将是不同的,如果orand人的功能; 在这种情况下,将在调用函数本身之前评估函数的参数.因此,operator.or_(yay(), operator.and_(nay(), nope()))印刷品yay,naynope即它打印所有三个,但仍按照从左至右.

您也可以将此概括为其他运营商.由于运算符优先级不同(使用隐式和显式(...)),以下两个表达式将产生不同的结果,但两次都会从左到右调用这些函数.

>>> def f(x): print(x); return x
>>> f(1) + f(2) * f(3) / f(4) ** f(5) - f(6)         # 1 2 3 4 5 6 -> -4.99
>>> (f(1) + f(2)) * (((f(3) / f(4)) ** f(5)) - f(6)) # 1 2 3 4 5 6 -> -17.29
Run Code Online (Sandbox Code Playgroud)

正如评论中所指出的,虽然操作之间的术语是从左到右进行评估,但实际操作是根据其优先级进行评估的.

class F:
    def __init__(self,x): self.x = x
    def __add__(self, other): print(f"add({self},{other})"); return F(self.x+other.x)
    def __mul__(self, other): print(f"mul({self},{other})"); return F(self.x*other.x)
    def __pow__(self, other): print(f"pow({self},{other})"); return F(self.x**other.x)
    def __repr__(self): return str(self.x)
def f(x): print(x); return F(x)
Run Code Online (Sandbox Code Playgroud)

这种方式中,表达f(1) + f(2) ** f(3) * f(4)被评价为1,2,3,pow(2,3),4,mul(8,4),add(1,32),即术语评价左到右(推栈上)和表达式只要它们的参数被评估评估.