【问题标题】:Confused about Operator Precedence in Python对 Python 中的运算符优先级感到困惑
【发布时间】:2019-11-10 02:18:18
【问题描述】:

我在 python 解释器中玩弄逻辑表达式,我似乎无法弄清楚 python 到底在使用什么执行过程。我已经看到这张表 (http://www.mathcs.emory.edu/~valerie/courses/fall10/155/resources/op_precedence.html) 描述了 python 使用的运算符优先级。

1)

print("this") or True and 1/0 and print("tester")

当我在 python 解释器中输入它时,我得到“this”的输出,然后是零除错误。但是,我引用的网站提到函数调用是第二高优先级,所以不应该先执行 print 的两个函数调用吗?我知道有短路评估,但不是只有在你达到 ands、nots 和 ors 的优先级后才会生效吗?

2)

True>False or print("hello")

即使这在 python 解释器上也只输出 True 。为什么不先调用 print 的函数呢?

3)

5 is 5 or 1/0

这会输出 True。但是除法的优先级不应该高于“is”吗?这个表达式不应该返回 ZeroDivsionError 吗?

有人可以解释我缺少什么以及如何判断 python 将按什么顺序执行逻辑表达式吗?

【问题讨论】:

  • 据我了解,优先顺序并不意味着评估顺序。解析器使用优先级来构造解析树(然后是语法树或一些 IR)。同样,这只是我的理解,我不知道 Python 是否也是如此。
  • 优先级不会取代逻辑运算符/短路。它只是指定在评估之前将哪些优先表达式组合在一起。
  • X or YX and Y 中,X总是首先被评估,而不管Y 中使用什么操作。否则不可能短路。
  • 既然您已经了解短路评估,请查看stackoverflow.com/questions/46506098/…
  • 好的,我想我已经掌握了这个窍门,谢谢大家!感谢您指出我的答案@Arne,这让事情变得更加清晰

标签: python python-3.x operators logical-operators operator-precedence


【解决方案1】:

有人可以解释我缺少什么以及如何判断 python 将按什么顺序执行逻辑表达式吗?

在解析为树时,优先级会影响“共享”操作数的分组方式。之后,每个子表达式的具体评估模型接管。

print("this") or True and 1/0 and print("tester")

你会得到一个看起来像这样的树(你可以使用ast 模块得到更详细但更精确的版本,并使用astpretty 得到可读的东西):

    or
        print("this")
        and
             True
             and
                 1/0
                 print("tester")

然后评估接管(在编译为字节码但不会改变操作顺序之后):

  1. 评估外部or
    1. 它评估第一个print,返回一个假值,因此
    2. 它评估第一个and
      1. 它评估 True 这是真实的
      2. 因此它评估第二个and
        1. 评估 1/0 会爆炸

True>False or print("hello")

这会解析为

or
   >
      True
      False
   print("hello")
  1. or 计算其第一个操作数

    1. (> True False) 计算为 True

    or 是一个短路运算符,一旦找到真值就会停止并返回,因此它永远不会到达print

5 is 5 or 1/0

这会解析为

or
    is
        5
        5
    /
        1
        0
  1. or 被评估

    1. is 被评估,并返回 True

    如上,or是短路操作符,返回第一个真值,所以立即返回。

我遗漏了一些内容,例如从技术上讲,/ 评估两个操作数然后应用其操作,函数调用评估它们的所有参数然后执行调用本身。

andor 脱颖而出,因为它们在评估每个操作数之后执行逻辑,而不是在评估所有操作数之后(它们是惰性/短路):and 返回第一个虚假结果获取或返回它得到的第一个真实结果,可能只评估它们的第一个操作数。

【讨论】:

  • 当然可以。与大多数运算符不同,“and”和“or”是触发对其操作数求值的运算符。操作数评估绝对不会先于操作员评估他们的情况,这就是为什么他们没有数据模型挂钩的部分原因。以及为什么1 or 1/0 执行得很好(在评估第一个操作数后它会短路)而1 | 1/0 没有(评估两个操作数,然后才评估运算符)。一般来说,您是正确的,但对于 andor,您是特别错误的,这就是重点。
【解决方案2】:

解析器使用优先顺序来构造解析树。与求值顺序不一样。

以您的第三种情况为例:5 is 5 or 1/0。优先顺序为/ > is > or

解析树看起来像这样(根据优先级)。

     or
   /    \
  is    div
 / \    / \
5   5  1   0

根据提供给代码生成器的另一条规则,评估(从技术上讲,代码生成)从顶部开始,在本例中为 or 节点。 or 的代码生成器的输出可能如下所示。

t = code(5 is 5)
if t goto L1
L2: code(1/0)
    goto L1
L1:

优先顺序最初仅用于创建解析树。一旦构建了解析树,语义规则(动作?我忘记了单词)就会发挥作用。

短路行为内置于or节点的语义规则中。

附言此答案不适用于 Python。

【讨论】:

  • 这只是华夫饼。优先级影响运算符的评估顺序。它不决定操作数的求值顺序。
  • @user207421 我看不出我的回答与你的陈述有何矛盾。
【解决方案3】:

优先级不会影响 python 评估语句的顺序。在5 is 5 or 1/0中,python首先检查5 is 5是否为真,如果是,则忽略第二条语句。换句话说,无论优先级如何,python 总是首先评估第一个语句

【讨论】:

  • 明白了。谢谢!
  • @purplejackfruit,请采纳最满意的答案!
  • 这个答案是完全错误的。 语句按照它们在源文件中出现的顺序进行评估,取决于方法/函数调用、条件和循环语句、返回和异常的语义。优先级不影响操作数 either 的计算顺序。它影响算子的评估顺序。
猜你喜欢
  • 2020-08-20
  • 1970-01-01
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多