From c6102c3021f15c9bc5ce41feb9dfb7297fdf505a Mon Sep 17 00:00:00 2001 From: Gabriele Bozzola Date: Thu, 29 Jul 2021 11:41:12 -0700 Subject: [PATCH] Swap math.pow with self.pow Before this commit, `pow` was the only binary function that doesn't use the corresponding operator but calls `pow` in `math`. This commit defines a `pow` function that invokes the corresponding operator (**). Using ** is preferable because it is slightly faster and preservers integers (see, https://www.semicolonworld.com/question/56223/exponentials-in-python-x-y-vs-math-pow-x-y). Moreover, it improves type compatibility, since now the function works with user-defined classes (as long as they have a __pow__ method), `math.pow` only supports numbers. --- py_expression_eval/__init__.py | 7 +++++-- py_expression_eval/tests.py | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 12 deletions(-) mode change 100644 => 100755 py_expression_eval/__init__.py diff --git a/py_expression_eval/__init__.py b/py_expression_eval/__init__.py old mode 100644 new mode 100755 index 69d19b1..d3d06b9 --- a/py_expression_eval/__init__.py +++ b/py_expression_eval/__init__.py @@ -239,6 +239,9 @@ def mul(self, a, b): def div(self, a, b): return a / b + def pow(self, a, b): + return a ** b + def mod(self, a, b): return a % b @@ -374,8 +377,8 @@ def __init__(self, string_literal_quotes = ("'", "\"")): '*': self.mul, '/': self.div, '%': self.mod, - '^': math.pow, - '**': math.pow, + '^': self.pow, + '**': self.pow, ',': self.append, '||': self.concat, "==": self.equal, diff --git a/py_expression_eval/tests.py b/py_expression_eval/tests.py index b296b44..4a1e90d 100755 --- a/py_expression_eval/tests.py +++ b/py_expression_eval/tests.py @@ -42,8 +42,8 @@ def test_parser(self): self.assertExactEqual(parser.parse('2 * 3').evaluate({}), 6) self.assertExactEqual(parser.parse(u'2 \u2219 3').evaluate({}), 6) self.assertExactEqual(parser.parse(u'2 \u2022 3').evaluate({}), 6) - self.assertExactEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8.0) - self.assertExactEqual(parser.parse('2 ** x').evaluate({'x': 3}), 8.0) + self.assertExactEqual(parser.parse('2 ^ x').evaluate({'x': 3}), 8) + self.assertExactEqual(parser.parse('2 ** x').evaluate({'x': 3}), 8) self.assertExactEqual(parser.parse('-1.E2 ** x + 2.0E2').evaluate({'x': 1}), 100.0) self.assertEqual(parser.parse('x < 3').evaluate({'x': 3}), False) self.assertEqual(parser.parse('x < 3').evaluate({'x': 2}), True) @@ -54,14 +54,14 @@ def test_parser(self): self.assertExactEqual(parser.parse('2 * x + 1').evaluate({'x': 3}), 7) self.assertExactEqual(parser.parse('2 + 3 * x').evaluate({'x': 4}), 14) self.assertExactEqual(parser.parse('(2 + 3) * x').evaluate({'x': 4}), 20) - self.assertExactEqual(parser.parse('2-3^x').evaluate({'x': 4}), -79.0) - self.assertExactEqual(parser.parse('-2-3^x').evaluate({'x': 4}), -83.0) - self.assertExactEqual(parser.parse('-3^x').evaluate({'x': 4}), -81.0) - self.assertExactEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81.0) - self.assertExactEqual(parser.parse('2-3**x').evaluate({'x': 4}), -79.0) - self.assertExactEqual(parser.parse('-2-3**x').evaluate({'x': 4}), -83.0) - self.assertExactEqual(parser.parse('-3**x').evaluate({'x': 4}), -81.0) - self.assertExactEqual(parser.parse('(-3)**x').evaluate({'x': 4}), 81.0) + self.assertExactEqual(parser.parse('2-3.0^x').evaluate({'x': 4}), -79.0) + self.assertExactEqual(parser.parse('-2-3.0^x').evaluate({'x': 4}), -83.0) + self.assertExactEqual(parser.parse('-3^x').evaluate({'x': 4}), -81) + self.assertExactEqual(parser.parse('(-3)^x').evaluate({'x': 4}), 81) + self.assertExactEqual(parser.parse('2-3**x').evaluate({'x': 4}), -79) + self.assertExactEqual(parser.parse('-2-3**x').evaluate({'x': 4}), -83) + self.assertExactEqual(parser.parse('-3.0**x').evaluate({'x': 4}), -81.0) + self.assertExactEqual(parser.parse('(-3.0)**x').evaluate({'x': 4}), 81.0) self.assertExactEqual(parser.parse('2*x + y').evaluate({'x': 4, 'y': 1}), 9) self.assertEqual(parser.parse("x||y").evaluate({'x': 'hello ', 'y': 'world'}), 'hello world') self.assertEqual(parser.parse("'x'||'y'").evaluate({}), 'xy')