下面的代码包含一个旧样式的划分。
(x / 2 * 3.0)
使用分配给 x 的任意值运行上述代码的结果应如下所示,其中括号明确显示操作(x / 2) * 3.0
的顺序。 或者以其他顺序编写,结果应评估为x * (3.0 / 2)
。
一旦我们在上面的代码上运行futurize
, old_div
就会被fix_division_safe
夹具插入。 然而,正如我们在下面的差异中看到的那样,该函数被调用的参数顺序错误。
$ futurize --stage2 src/example.py
RefactoringTool: Refactored src/example.py
--- src/example.py (original)
+++ src/example.py (refactored)
@@ -1 +1,3 @@
-(x / 2 * 3.0)
+from __future__ import division
+from past.utils import old_div
+(old_div(x, 2 * 3.0))
RefactoringTool: Files that need to be modified:
RefactoringTool: src/example.py
正如“预期结果”一节中所述,正确的转换应该是: (old_div(x, 2) * 3.0)
或者以其他顺序编写,结果应评估为
x * (3.0 / 2)
。
虽然在数学上是等价的,但这在 Python 2 上并不相等。如果x
是int
,则x / 2
在某些情况下将首先截断,而(3.0 / 2)
将始终为 1.5 且永不截断。
当然,这不会改变错误。
我也这么认为,这就是为什么我使用 Python 2.7.15 和 Python 3.7.1 来运行示例并验证它们是否显示相同的行为。 很高兴听到我的最初意图并非完全错误。
也许它也连接到操作系统? 我在 Windows 7 x64 上运行示例。
你能举一个例子,在哪种情况下 Python 2 会以另一种方式评估表达式?
>>> y = range(10)
>>> [x / 2 * 3.0 for x in y]
[0.0, 0.0, 3.0, 3.0, 6.0, 6.0, 9.0, 9.0, 12.0, 12.0]
>>> [x * (3.0 / 2) for x in y]
[0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5, 12.0, 13.5]
(您的预期转换当然是正确的结果。)
完全符合我的预期。 但是,我明确地对 x 使用 1 进行了测试,结果得到了 1.5。
我还忘了提到,如果不使用括号,代码的输出会有所不同。 在这种情况下,futurize 将产生正确的转换。
1 / 2 * 3.0
- - > old_div(1, 2) * 3.0
我遇到了同样的错误,正在我的分支上进行修复。
我的更改似乎解决了这个问题,如下所示:
$ cat sample.py
x = 10
(x / 2 * 3.0)
原始输出
$ futurize sample.py
RefactoringTool: Skipping optional fixer: idioms
RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: Refactored sample.py
--- sample.py (original)
+++ sample.py (refactored)
@@ -1,2 +1,4 @@
+from __future__ import division
+from past.utils import old_div
x = 10
-(x / 2 * 3.0)
+(old_div(x, 2 * 3.0))
RefactoringTool: Files that need to be modified:
RefactoringTool: sample.py
新输出
$ futurize sample.py
RefactoringTool: Skipping optional fixer: idioms
RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: Refactored sample.py
--- sample.py (original)
+++ sample.py (refactored)
@@ -1,2 +1,4 @@
+from __future__ import division
+from past.utils import old_div
x = 10
-(x / 2 * 3.0)
+(old_div(x, 2) * 3.0)
RefactoringTool: Files that need to be modified:
RefactoringTool: sample.py
当我看到时间时,我将创建一个拉取请求..
这里有更多的例子。
我还忘了提到,如果不使用括号,代码的输出会有所不同。 在这种情况下,futurize 将产生正确的转换。
1 / 2 * 3.0
- - >old_div(1, 2) * 3.0
与您所说的相反,我看到1 / 2 * 3.0
使用 master 上的当前代码错误地转换为old_div(1, 2 * 3.0)
。
$ cat sample2.py
1 / 2 * 3.0
x = 10
x / 2
x / 2.0
x / 2 * 3
x / (2 * 3)
x * 2 / 3
原始输出
$ futurize sample2.py
RefactoringTool: Skipping optional fixer: idioms
RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: Refactored sample2.py
--- sample2.py (original)
+++ sample2.py (refactored)
@@ -1,7 +1,9 @@
-1 / 2 * 3.0
+from __future__ import division
+from past.utils import old_div
+old_div(1, 2 * 3.0)
x = 10
-x / 2
+old_div(x, 2)
x / 2.0
-x / 2 * 3
-x / (2 * 3)
-x * 2 / 3
+old_div(x, 2 * 3)
+old_div(x, (2 * 3))
+old_div(x * 2, 3)
RefactoringTool: Files that need to be modified:
RefactoringTool: sample2.py
新输出
$ futurize sample2.py
RefactoringTool: Skipping optional fixer: idioms
RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: Refactored sample2.py
--- sample2.py (original)
+++ sample2.py (refactored)
@@ -1,7 +1,9 @@
-1 / 2 * 3.0
+from __future__ import division
+from past.utils import old_div
+old_div(1, 2) * 3.0
x = 10
-x / 2
+old_div(x, 2)
x / 2.0
-x / 2 * 3
-x / (2 * 3)
-x * 2 / 3
+old_div(x, 2) * 3
+old_div(x, (2 * 3))
+old_div(x * 2, 3)
RefactoringTool: Files that need to be modified:
RefactoringTool: sample2.py
PR 创建 (https://github.com/PythonCharmers/python-future/pull/441)
我还观察到,即使左右操作数都是浮点数, old_div
也会被插入,例如
1.0/1024.0
变成
old_div(1.0,1024.0)
我认为这种转换是不必要的,因为在 Python 2 和 Python 3 中,两个操作数都是浮点数的除法会产生相同的结果。
@mattgathu你使用哪个版本的futurize 和 Python? 使用 Python 3.7.2 和 futurize 0.17.1(PyPI 中的最新版本),当futurize
d 时1.0/1024.0
保持不变。
$ python --version
Python 3.7.2
$ futurize --version
0.17.1
$ cat test.py
1.0 / 1024.0
1 / 1024.0
1.0 / 1024
$ futurize test.py
RefactoringTool: Skipping optional fixer: idioms
RefactoringTool: Skipping optional fixer: ws_comma
RefactoringTool: No files need to be modified.
这是我的版本:
$ python -V
Python 2.7.16
$ futurize --version
0.16.0
我已经升级到0.17.0 ,似乎没有这个问题。 谢谢
事实上,v0.17.0 似乎包含一个增强功能,可以跳过不必要的转换。
https://github.com/PythonCharmers/python-future/releases/tag/v0.17.0
修复 fix_division_safe 以支持更好的复杂表达式转换,并跳过明显的浮点除法。
我也有这个问题,在 Python 2.7.16 上运行 futurize 0.17.1。 这个例子说明了这个问题:
$ echo 'x = 100/10 * 10' | futurize --stage2 -
RefactoringTool: Refactored <stdin>
--- <stdin> (original)
+++ <stdin> (refactored)
@@ -1 +1,3 @@
-x = 100/10 * 10
+from __future__ import division
+from past.utils import old_div
+x = old_div(100,10 * 10)
RefactoringTool: Files that need to be modified:
RefactoringTool: <stdin>
请注意, 100/10 * 10
(==100) 被转换为old_div(100,10 * 10)
(==1)。 这对我来说似乎是一个主要错误。
最有用的评论
我也有这个问题,在 Python 2.7.16 上运行 futurize 0.17.1。 这个例子说明了这个问题:
请注意,
100/10 * 10
(==100) 被转换为old_div(100,10 * 10)
(==1)。 这对我来说似乎是一个主要错误。