Some small updates, with Jeffrey's OK.
This commit is contained in:
parent
3a6f48c056
commit
e8400c12a9
85
pep-3141.txt
85
pep-3141.txt
|
@ -60,8 +60,8 @@ numbers are supported by this hierarchy. ::
|
||||||
class Complex(Number):
|
class Complex(Number):
|
||||||
"""Complex defines the operations that work on the builtin complex type.
|
"""Complex defines the operations that work on the builtin complex type.
|
||||||
|
|
||||||
In short, those are: a conversion to complex, .real, .imag, +, -,
|
In short, those are: conversion to complex, bool(), .real, .imag,
|
||||||
*, /, abs(), .conjugate, ==, and !=.
|
+, -, *, /, **, abs(), .conjugate(), ==, and !=.
|
||||||
|
|
||||||
If it is given heterogenous arguments, and doesn't have special
|
If it is given heterogenous arguments, and doesn't have special
|
||||||
knowledge about them, it should fall back to the builtin complex
|
knowledge about them, it should fall back to the builtin complex
|
||||||
|
@ -105,10 +105,7 @@ numbers are supported by this hierarchy. ::
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def __pos__(self):
|
def __pos__(self):
|
||||||
"""+self
|
"""Coerces self to whatever class defines the method."""
|
||||||
|
|
||||||
Coerces self to whatever class defines the method.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other):
|
||||||
|
@ -127,6 +124,7 @@ numbers are supported by this hierarchy. ::
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __div__(self, other):
|
def __div__(self, other):
|
||||||
|
"""a/b; should promote to float or complex when necessary."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -135,7 +133,7 @@ numbers are supported by this hierarchy. ::
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __pow__(self, exponent):
|
def __pow__(self, exponent):
|
||||||
"""Like division, a**b should promote to complex when necessary."""
|
"""a**b; should promote to float or complex when necessary."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -156,8 +154,7 @@ numbers are supported by this hierarchy. ::
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def __ne__(self, other):
|
# __ne__ is inherited from object and negates whatever __eq__ does.
|
||||||
return not (self == other)
|
|
||||||
|
|
||||||
|
|
||||||
The ``Real`` ABC indicates that the value is on the real line, and
|
The ``Real`` ABC indicates that the value is on the real line, and
|
||||||
|
@ -167,12 +164,15 @@ totally ordered except for NaNs (which this PEP basically ignores). ::
|
||||||
class Real(Complex):
|
class Real(Complex):
|
||||||
"""To Complex, Real adds the operations that work on real numbers.
|
"""To Complex, Real adds the operations that work on real numbers.
|
||||||
|
|
||||||
In short, those are: a conversion to float, trunc(), divmod,
|
In short, those are: conversion to float, trunc(), math.floor(),
|
||||||
%, <, <=, >, and >=.
|
math.ceil(), round(), divmod(), //, %, <, <=, >, and >=.
|
||||||
|
|
||||||
Real also provides defaults for the derived operations.
|
Real also provides defaults for some of the derived operations.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# XXX What to do about the __int__ implementation that's
|
||||||
|
# currently present on float and Decimal? Get rid of it?
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __float__(self):
|
def __float__(self):
|
||||||
"""Any Real can be converted to a native float object."""
|
"""Any Real can be converted to a native float object."""
|
||||||
|
@ -183,10 +183,10 @@ totally ordered except for NaNs (which this PEP basically ignores). ::
|
||||||
"""Truncates self to an Integral.
|
"""Truncates self to an Integral.
|
||||||
|
|
||||||
Returns an Integral i such that:
|
Returns an Integral i such that:
|
||||||
* i>=0 iff self>0
|
* i>=0 iff self>0;
|
||||||
* abs(i) <= abs(self).
|
* abs(i) <= abs(self);
|
||||||
* for any Integral j satisfying the first two conditions,
|
* for any Integral j satisfying the first two conditions,
|
||||||
abs(i) >= abs(j) [i.e. i has "maximal" abs among those]
|
abs(i) >= abs(j) [i.e. i has "maximal" abs among those].
|
||||||
i.e. "truncate towards 0".
|
i.e. "truncate towards 0".
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -205,7 +205,7 @@ totally ordered except for NaNs (which this PEP basically ignores). ::
|
||||||
def __round__(self, ndigits:Integral=None):
|
def __round__(self, ndigits:Integral=None):
|
||||||
"""Rounds self to ndigits decimal places, defaulting to 0.
|
"""Rounds self to ndigits decimal places, defaulting to 0.
|
||||||
|
|
||||||
If ndigits is omitted, returns an Integral, otherwise
|
If ndigits is omitted or None, returns an Integral, otherwise
|
||||||
returns a Real. Rounds half toward even.
|
returns a Real. Rounds half toward even.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -261,14 +261,18 @@ totally ordered except for NaNs (which this PEP basically ignores). ::
|
||||||
def __le__(self, other):
|
def __le__(self, other):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# __gt__ and __ge__ are automatically done by reversing the arguments.
|
||||||
|
# (But __le__ is not computed as the opposite of __gt__!)
|
||||||
|
|
||||||
# Concrete implementations of Complex abstract methods.
|
# Concrete implementations of Complex abstract methods.
|
||||||
|
# Subclasses may override these, but don't have to.
|
||||||
|
|
||||||
def __complex__(self):
|
def __complex__(self):
|
||||||
return complex(float(self))
|
return complex(float(self))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def real(self):
|
def real(self):
|
||||||
return self
|
return +self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def imag(self):
|
def imag(self):
|
||||||
|
@ -276,10 +280,10 @@ totally ordered except for NaNs (which this PEP basically ignores). ::
|
||||||
|
|
||||||
def conjugate(self):
|
def conjugate(self):
|
||||||
"""Conjugate is a no-op for Reals."""
|
"""Conjugate is a no-op for Reals."""
|
||||||
return self
|
return +self
|
||||||
|
|
||||||
|
|
||||||
We need to clean up Demo/classes/Rat.py and promote it into
|
We should clean up Demo/classes/Rat.py and promote it into
|
||||||
rational.py in the standard library. Then it will implement the
|
rational.py in the standard library. Then it will implement the
|
||||||
Rational ABC. ::
|
Rational ABC. ::
|
||||||
|
|
||||||
|
@ -295,6 +299,7 @@ Rational ABC. ::
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
# Concrete implementation of Real's conversion to float.
|
# Concrete implementation of Real's conversion to float.
|
||||||
|
# (This invokes Integer.__div__().)
|
||||||
|
|
||||||
def __float__(self):
|
def __float__(self):
|
||||||
return self.numerator / self.denominator
|
return self.numerator / self.denominator
|
||||||
|
@ -310,21 +315,25 @@ And finally integers::
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def __index__(self):
|
def __index__(self):
|
||||||
|
"""__index__() exists because float and Decimal have __int__()."""
|
||||||
return int(self)
|
return int(self)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __pow__(self, exponent, modulus):
|
def __pow__(self, exponent, modulus=None):
|
||||||
"""self ** exponent % modulus, but maybe faster.
|
"""self ** exponent % modulus, but maybe faster.
|
||||||
|
|
||||||
Implement this if you want to support the 3-argument version
|
Implement this if you want to support the 3-argument
|
||||||
of pow(). Otherwise, just implement the 2-argument version
|
version of pow(). Otherwise, just implement the 2-argument
|
||||||
described in Complex. Raise a TypeError if exponent < 0 or any
|
version described in Complex. If modulus is None, this
|
||||||
argument isn't Integral.
|
should behave as the 2-argument version; otherwise, raise
|
||||||
|
a TypeError if exponent < 0 or any argument isn't
|
||||||
|
Integral.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __lshift__(self, other):
|
def __lshift__(self, other):
|
||||||
|
"""i<<j returns i * 2**j."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -333,6 +342,7 @@ And finally integers::
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __rshift__(self, other):
|
def __rshift__(self, other):
|
||||||
|
"""i>>j returns i // 2**j."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
@ -374,7 +384,7 @@ And finally integers::
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def numerator(self):
|
def numerator(self):
|
||||||
return self
|
return +self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def denominator(self):
|
def denominator(self):
|
||||||
|
@ -390,7 +400,7 @@ you would expect. For example, it is possible for ``(X + -X) + 3 ==
|
||||||
functions deal with this isn't a problem, but it is something to be
|
functions deal with this isn't a problem, but it is something to be
|
||||||
aware of.
|
aware of.
|
||||||
|
|
||||||
Therefore, I define ``Exact`` and ``Inexact`` ABCs to mark whether
|
Therefore, we define ``Exact`` and ``Inexact`` ABCs to mark whether
|
||||||
types have this problem. Every instance of ``Integral`` and
|
types have this problem. Every instance of ``Integral`` and
|
||||||
``Rational`` should be Exact, but ``Reals`` and ``Complexes`` may or
|
``Rational`` should be Exact, but ``Reals`` and ``Complexes`` may or
|
||||||
may not be. (Do we really only need one of these, and the other is
|
may not be. (Do we really only need one of these, and the other is
|
||||||
|
@ -404,7 +414,7 @@ Changes to operations and __magic__ methods
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
To support more precise narrowing from float to int (and more
|
To support more precise narrowing from float to int (and more
|
||||||
generally, from Real to Integral), I'm proposing the following new
|
generally, from Real to Integral), we propose the following new
|
||||||
__magic__ methods, to be called from the corresponding library
|
__magic__ methods, to be called from the corresponding library
|
||||||
functions. All of these return Integrals rather than Reals.
|
functions. All of these return Integrals rather than Reals.
|
||||||
|
|
||||||
|
@ -418,12 +428,14 @@ functions. All of these return Integrals rather than Reals.
|
||||||
least Integral ``>= x``.
|
least Integral ``>= x``.
|
||||||
|
|
||||||
4. ``__round__(self)``, called from ``round(x)``, which returns the
|
4. ``__round__(self)``, called from ``round(x)``, which returns the
|
||||||
Integral closest to ``x``, rounding half toward even. The
|
Integral closest to ``x``, rounding half toward even. There is also
|
||||||
2-argument version should return a Real.
|
a 2-argument version, ``__round__(self, other)``, called from
|
||||||
|
``round(x, y)``, which should return a Real.
|
||||||
|
|
||||||
Because the ``int()`` conversion from ``float`` is equivalent to but
|
Because the ``int()`` conversion implemented by ``float`` (and by
|
||||||
less explicit than ``trunc()``, let's remove it. (Or, if that breaks
|
``decimal.Decimal``) is equivalent to but less explicit than
|
||||||
too much, just add a deprecation warning.)
|
``trunc()``, let's remove it. (Or, if that breaks too much, just add a
|
||||||
|
deprecation warning.)
|
||||||
|
|
||||||
``complex.__{divmod,mod,floordiv,int,float}__`` also go away. It would
|
``complex.__{divmod,mod,floordiv,int,float}__`` also go away. It would
|
||||||
be nice to provide a nice error message to help confused porters, but
|
be nice to provide a nice error message to help confused porters, but
|
||||||
|
@ -519,14 +531,14 @@ Rejected Alternatives
|
||||||
The initial version of this PEP defined an algebraic hierarchy
|
The initial version of this PEP defined an algebraic hierarchy
|
||||||
inspired by a Haskell Numeric Prelude [#numericprelude]_ including
|
inspired by a Haskell Numeric Prelude [#numericprelude]_ including
|
||||||
MonoidUnderPlus, AdditiveGroup, Ring, and Field, and mentioned several
|
MonoidUnderPlus, AdditiveGroup, Ring, and Field, and mentioned several
|
||||||
other possible algebraic types before getting to the numbers. I had
|
other possible algebraic types before getting to the numbers. We had
|
||||||
expected this to be useful to people using vectors and matrices, but
|
expected this to be useful to people using vectors and matrices, but
|
||||||
the NumPy community really wasn't interested, and we ran into the
|
the NumPy community really wasn't interested, and we ran into the
|
||||||
issue that even if ``x`` is an instance of ``X <: MonoidUnderPlus``
|
issue that even if ``x`` is an instance of ``X <: MonoidUnderPlus``
|
||||||
and ``y`` is an instance of ``Y <: MonoidUnderPlus``, ``x + y`` may
|
and ``y`` is an instance of ``Y <: MonoidUnderPlus``, ``x + y`` may
|
||||||
still not make sense.
|
still not make sense.
|
||||||
|
|
||||||
Then I gave the numbers a much more branching structure to include
|
Then we gave the numbers a much more branching structure to include
|
||||||
things like the Gaussian Integers and Z/nZ, which could be Complex but
|
things like the Gaussian Integers and Z/nZ, which could be Complex but
|
||||||
wouldn't necessarily support things like division. The community
|
wouldn't necessarily support things like division. The community
|
||||||
decided that this was too much complication for Python, so I've now
|
decided that this was too much complication for Python, so I've now
|
||||||
|
@ -540,10 +552,11 @@ References
|
||||||
.. [#pep3119] Introducing Abstract Base Classes
|
.. [#pep3119] Introducing Abstract Base Classes
|
||||||
(http://www.python.org/dev/peps/pep-3119/)
|
(http://www.python.org/dev/peps/pep-3119/)
|
||||||
|
|
||||||
.. [#classtree] Possible Python 3K Class Tree?, wiki page created by Bill Janssen
|
.. [#classtree] Possible Python 3K Class Tree?, wiki page by Bill Janssen
|
||||||
(http://wiki.python.org/moin/AbstractBaseClasses)
|
(http://wiki.python.org/moin/AbstractBaseClasses)
|
||||||
|
|
||||||
.. [#numericprelude] NumericPrelude: An experimental alternative hierarchy of numeric type classes
|
.. [#numericprelude] NumericPrelude: An experimental alternative hierarchy
|
||||||
|
of numeric type classes
|
||||||
(http://darcs.haskell.org/numericprelude/docs/html/index.html)
|
(http://darcs.haskell.org/numericprelude/docs/html/index.html)
|
||||||
|
|
||||||
.. [#schemetower] The Scheme numerical tower
|
.. [#schemetower] The Scheme numerical tower
|
||||||
|
|
Loading…
Reference in New Issue