Skip to content

Commit 97ff9ef

Browse files
committed
Another attempt to make mypy happy.
Actually, the type returned on Number was incorrect. Also, order methods in Complex in alphbetic order. Clarify the purpose of `.value` versus `.to_python()`.
1 parent 804d2af commit 97ff9ef

File tree

1 file changed

+84
-67
lines changed

1 file changed

+84
-67
lines changed

mathics/core/atoms.py

Lines changed: 84 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class Number(Atom, ImmutableValueMixin, NumericOperators, Generic[T]):
5454
being: Integer, Rational, Real, Complex.
5555
"""
5656

57-
_value: T
57+
_value: Union[int, float, complex]
5858
hash: int
5959

6060
def __getnewargs__(self):
@@ -149,10 +149,16 @@ def round(self, d: Optional[int] = None) -> "Number":
149149
return self
150150

151151
@property
152-
def value(self) -> T:
153-
"""Equivalent value in either SymPy's or Python's native
154-
datatype if that exist. Note the SymPy value
155-
and the Python value might be the same thing.
152+
def value(self) -> Union[complex, float, int]:
153+
"""Equivalent value in Python's native datatype. In
154+
some cases, like PrecisionReal and Complex, Mathics3's
155+
representation is more precise and is only approximately the
156+
same value. In those cases, use method use is_exact_value() to
157+
determine whether ".value" is exact or approximate.
158+
159+
.value and .to_python are simililar, but .to_python is not a
160+
property, and allows for fancy options which might influence
161+
conversion. Also, .value is a property for other atoms.
156162
"""
157163
return self._value
158164

@@ -817,6 +823,14 @@ def __new__(cls, real, imag):
817823

818824
return self
819825

826+
@cache
827+
def __getnewargs__(self):
828+
return (self.real, self.imag)
829+
830+
@cache
831+
def __neg__(self):
832+
return Complex(-self.real, -self.imag)
833+
820834
def __hash__(self):
821835
return self.hash
822836

@@ -829,27 +843,6 @@ def atom_to_boxes(self, f, evaluation):
829843

830844
return format_element(self, evaluation, f)
831845

832-
def to_sympy(self, **kwargs):
833-
return self.real.to_sympy() + sympy.I * self.imag.to_sympy()
834-
835-
@cache
836-
def to_python(self, *args, **kwargs) -> Union[int, float, complex]:
837-
"""
838-
Returns a Python equivalent value for this complex number.
839-
"""
840-
if self.imag.sameQ(Integer0):
841-
return self.real.to_python(*args, **kwargs)
842-
843-
return complex(
844-
self.real.to_python(*args, **kwargs), self.imag.to_python(*args, **kwargs)
845-
)
846-
847-
@cache
848-
def to_mpmath(self, precision: Optional[int] = None):
849-
return mpmath.mpc(
850-
self.real.to_mpmath(precision), self.imag.to_mpmath(precision)
851-
)
852-
853846
@cache
854847
def default_format(self, evaluation, form) -> str:
855848
return "Complex[%s, %s]" % (
@@ -870,25 +863,6 @@ def element_order(self) -> tuple:
870863
1,
871864
)
872865

873-
@property
874-
def pattern_precedence(self) -> tuple:
875-
"""
876-
Return a precedence value, a tuple, which is used in selecting
877-
which pattern to select when several match.
878-
"""
879-
return super().pattern_precedence
880-
881-
def sameQ(self, rhs) -> bool:
882-
"""Mathics SameQ"""
883-
return (
884-
isinstance(rhs, Complex) and self.real == rhs.real and self.imag == rhs.imag
885-
)
886-
887-
def round(self, d=None) -> "Complex":
888-
real = self.real.round(d)
889-
imag = self.imag.round(d)
890-
return Complex(real, imag)
891-
892866
@property
893867
def is_exact(self) -> bool:
894868
if self.real.is_machine_precision() or self.imag.is_machine_precision():
@@ -920,43 +894,36 @@ def get_float_value(self, permit_complex=False) -> Optional[complex]:
920894
return complex(real, imag)
921895
return None
922896

923-
@cache
924-
def get_precision(self) -> Optional[int]:
925-
"""Returns the default specification for precision in N and other numerical functions.
926-
When `None` is be returned no precision is has been defined and this object's value is
927-
exact.
928-
929-
This function is called by method `is_inexact()`.
930-
"""
931-
real_prec = self.real.get_precision()
932-
imag_prec = self.imag.get_precision()
933-
if imag_prec is None or real_prec is None:
934-
return None
935-
return min(real_prec, imag_prec)
936-
937897
def do_copy(self) -> "Complex":
938898
return Complex(self.real.do_copy(), self.imag.do_copy())
939899

940-
def user_hash(self, update) -> None:
941-
update(b"System`Complex>")
942-
update(self.real)
943-
update(self.imag)
944-
945900
def __eq__(self, other) -> bool:
946901
if isinstance(other, Complex):
947902
return self.real == other.real and self.imag == other.imag
948903
else:
949904
return super().__eq__(other)
950905

906+
@cache
951907
def __getnewargs__(self):
952908
return (self.real, self.imag)
953909

910+
@cache
954911
def __neg__(self):
955912
return Complex(-self.real, -self.imag)
956913

957-
@property
958-
def is_zero(self) -> bool:
959-
return self.real.is_zero and self.imag.is_zero
914+
@cache
915+
def get_precision(self) -> Optional[int]:
916+
"""Returns the default specification for precision in N and other numerical functions.
917+
When `None` is be returned no precision is has been defined and this object's value is
918+
exact.
919+
920+
This function is called by method `is_inexact()`.
921+
"""
922+
real_prec = self.real.get_precision()
923+
imag_prec = self.imag.get_precision()
924+
if imag_prec is None or real_prec is None:
925+
return None
926+
return min(real_prec, imag_prec)
960927

961928
@property
962929
def is_approx_zero(self) -> bool:
@@ -972,6 +939,56 @@ def is_approx_zero(self) -> bool:
972939
)
973940
return real_zero and imag_zero
974941

942+
@property
943+
def is_zero(self) -> bool:
944+
return self.real.is_zero and self.imag.is_zero
945+
946+
@property
947+
def pattern_precedence(self) -> tuple:
948+
"""
949+
Return a precedence value, a tuple, which is used in selecting
950+
which pattern to select when several match.
951+
"""
952+
return super().pattern_precedence
953+
954+
def sameQ(self, rhs) -> bool:
955+
"""Mathics SameQ"""
956+
return (
957+
isinstance(rhs, Complex) and self.real == rhs.real and self.imag == rhs.imag
958+
)
959+
960+
def round(self, d=None) -> "Complex":
961+
real = self.real.round(d)
962+
imag = self.imag.round(d)
963+
return Complex(real, imag)
964+
965+
@cache
966+
def to_mpmath(self, precision: Optional[int] = None):
967+
return mpmath.mpc(
968+
self.real.to_mpmath(precision), self.imag.to_mpmath(precision)
969+
)
970+
971+
@cache
972+
def to_python(self, *args, **kwargs) -> Union[int, float, complex]:
973+
"""
974+
Returns a Python equivalent value for this complex number.
975+
"""
976+
if self.imag.sameQ(Integer0):
977+
return self.real.to_python(*args, **kwargs)
978+
979+
return complex(
980+
self.real.to_python(*args, **kwargs), self.imag.to_python(*args, **kwargs)
981+
)
982+
983+
@cache
984+
def to_sympy(self, **kwargs):
985+
return self.real.to_sympy() + sympy.I * self.imag.to_sympy()
986+
987+
def user_hash(self, update) -> None:
988+
update(b"System`Complex>")
989+
update(self.real)
990+
update(self.imag)
991+
975992

976993
class Rational(Number[sympy.Rational]):
977994
class_head_name = "System`Rational"

0 commit comments

Comments
 (0)