Python-future: تحويل خاطئ للقسمة إلى old_div

تم إنشاؤها على ٣٠ يناير ٢٠١٩  ·  12تعليقات  ·  مصدر: PythonCharmers/python-future

رمز المثال

يحتوي الكود التالي على تقسيم النمط القديم.

(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)

0.18 bug

التعليق الأكثر فائدة

لدي أيضًا هذه المشكلة ، تشغيل Futurize 0.17.1 على Python 2.7.16. يوضح هذا المثال المشكلة:

$ 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). هذا يبدو وكأنه خطأ كبير بالنسبة لي.

ال 12 كومينتر

أو مكتوبة بترتيب آخر يجب تقييم النتيجة على أنها 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]

(التحويل المتوقع هو بالطبع النتيجة الصحيحة.)

تماما ما كنت أتوقعه. ومع ذلك ، فقد اختبرت بشكل صريح باستخدام 1 لـ x وحصلت على 1.5 نتيجة لذلك.

لقد نسيت أيضًا أن أذكر أن هناك إخراجًا مختلفًا للكود إذا لم تستخدم الأقواس. في هذه الحالة سوف تسفر العقود الآجلة عن التحويل الصحيح.

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

سأقوم بإنشاء طلب سحب عندما أرى الوقت ..

هنا المزيد من الأمثلة.

لقد نسيت أيضًا أن أذكر أن هناك إخراجًا مختلفًا للكود إذا لم تستخدم الأقواس. في هذه الحالة سوف تسفر العقود الآجلة عن التحويل الصحيح.

1 / 2 * 3.0 - -> old_div(1, 2) * 3.0

على عكس ما قلته ، أرى أن 1 / 2 * 3.0 تم تحويله إلى 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

تم إنشاء العلاقات العامة (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 ما هو إصدار Futureize و Python الذي تستخدمه؟ مع Python 3.7.2 و Futurize 0.17.1 (الأحدث في PyPI) ، يظل 1.0/1024.0 كما هو عند futurize d.

$ 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 لدعم تحويل أفضل للتعبيرات المعقدة وتخطي تقسيم التعويم الواضح.

لدي أيضًا هذه المشكلة ، تشغيل Futurize 0.17.1 على Python 2.7.16. يوضح هذا المثال المشكلة:

$ 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). هذا يبدو وكأنه خطأ كبير بالنسبة لي.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات