Some small updates, with Jeffrey's OK.

This commit is contained in:
Guido van Rossum 2007-12-06 17:49:44 +00:00
parent 3a6f48c056
commit e8400c12a9
1 changed files with 49 additions and 36 deletions

View File

@ -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