你混淆了运算符优先级和求值顺序。表达式
r = x or y and z
不是被评估为
tmp = y and z; r = x or tmp
, 而只是
r = x or (y and z)
。这个表达式从左到右被评估,如果
or
的结果已经确定,那么
(y and z)
将根本不会被评估。请注意,如果
or
和
and
是函数,则情况会有所不同; 在这种情况下,函数的参数在调用函数本身之前将被评估。因此,
operator.or_(yay(), operator.and_(nay(), nope()))
打印
yay
,
nay
和
nope
,即按顺序从左到右打印所有三个。你也可以将其推广到其他运算符上,两个表达式将由于不同的运算符优先级(包括隐式和显式使用
(...)
)而产生不同的结果,但两次都是从左到右调用函数。
>>> 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
正如评论中所指出的,虽然操作符之间的术语是从左到右进行评估的,但实际操作是根据它们的优先级进行评估的。
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)
这样,表达式f(1) + f(2) ** f(3) * f(4)
会按顺序计算并推入堆栈:1
, 2
, 3
, pow(2,3)
, 4
, mul(8,4)
, add(1,32)
。表达式参数一旦被计算,表达式就被立即计算。