【问题标题】:Basic operation giving different results in Python在 Python 中给出不同结果的基本操作
【发布时间】:2020-12-03 11:57:18
【问题描述】:

我在 Python 3 中使用了一些基本操作并遇到了这个

代码 1:

a = 6
b = 3
a = a / 2 * b
print(a)

输出是9.0

在我见过的其中一个培训中

a = a / 2 

可以写成

a /= 2

所以我重写了我上面的代码如下

代码 2:

a = 6
b = 3
a /= 2 * b
print(a)

但现在输出是1.0。 我期待 9.0 作为输出。有人能帮我理解为什么代码会这样吗?

【问题讨论】:

  • 这是关于操作的优先级...第一个是(a / 2) * b;第二个a / (2 * b)
  • 这里没有括号..当我没有括号时python会假设有括号吗?
  • python 做出了(记录在案的 [从左到右])的选择。它必须。你似乎也在这里想象括号......只是不是围绕相同的操作。
  • 添加了一个答案;我的回复太长,无法发表评论。

标签: python


【解决方案1】:

a /= 2 * b的情况下,你说a会被/=后面的表达式除。

换句话说,您的表达式可以重写为a = a / (2 * b),其中a = 6, b = 3

【讨论】:

  • 好的..明白了..但在这种情况下,说 a = a / 2 和 a /= 2 总是等价的,对吧?
【解决方案2】:

a /= 2 * b

首先执行 2 * b 所以如果 b == 3 它可以重写为:

a /= 6

【讨论】:

    【解决方案3】:

    那是因为它们以不同的顺序执行操作。

    第一个代码块将 a (6) 除以 2,然后将结果乘以 b (3)

    例如(6 / 2) * 3 = 9

    但是第二个代码块做了以下事情:

    6 / (2 * 3) = 1

    【讨论】:

      【解决方案4】:

      请注意,

      a /= 2 * b
      

      基本上是

      a = a / (2 * b)
      

      前面的代码不同。和上面不一样(看括号)

      a = a / 2 * b
      

      这不同于

      a = a / (2 * b)
      

      因为第一个代码将其解释为除法然后乘法,而第二个代码将其解释为乘法(底部)然后除法。

      【讨论】:

      • 这是否意味着,即使我没有明确提到括号,python 在第二种情况下也会这样?
      • @AbrahamPanicker 每种语言都这样做。这不是关于 python,而是关于算法。
      【解决方案5】:

      正如您在documentatiopn on operator precedence 中看到的,*/ 具有相同的优先级。从左到右依次执行两个优先级相同的操作:

      同一框组中的运算符从左到右

      所以你的第一个例子被评估为

      (a / 2) * b
      

      第二个

      a / (2 * b)
      

      关于您的评论

      a = a / 2a /= 2 总是等价的,对吧?

      对于内置的python数字,你是对的。

      对于您自己的类,您可以使操作有所不同。如果a 是自定义类的实例,a/x 将调用__truediv__(self, other)a/=x 将调用__itruediv__(self, other),如data model 中所述。

      【讨论】:

      • 是的..我得到了获得不同值背后的逻辑,但是我的问题是我们怎么能说 a = a / 2 和 a /= 2 总是等价的。这完全取决于第一个表达式之后是否还有其他表达式
      • 你有一个例子来说明你的意思吗?在/= 的情况下,右侧的所有内容都将在除法(和赋值)之前计算。
      • 是的...您可以在右侧添加任何其他操作,并将其全部视为同一括号的一部分,并在除法之前进行评估,例如。 a /= 2 * b + a 等价于 a = a / (2 * b + a)
      【解决方案6】:

      我很惊讶其他答案都没有提到这一点,但原因与数学、运算顺序或隐式括号没有任何关系。

      x /= y 只是x.__itruediv__(y) 的另一种说法。您的第二个示例不等同于您的第一个示例,因为参数在传递给函数调用之前进行了评估。所以,a /= 2 * b 等价于a.__itruediv__(2 * b),当然,表达式2 * b 必须在传递给__itruediv__ 之前进行计算。

      【讨论】:

      • Hiro 在之前的评论中提到了它并给出了 python 的数据模型文档的链接:)
      猜你喜欢
      • 2015-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多