Merged revisions 60481,60485,60489-60492,60494-60496,60498-60499,60501-60503,60505-60506,60508-60509,60523-60524,60532,60543,60545,60547-60548,60552,60554,60556-60559,60561-60562,60569,60571-60572,60574,60576-60583,60585-60586,60589,60591,60594-60595,60597-60598,60600-60601,60606-60612,60615,60617,60619-60621,60623-60625,60627-60629,60631,60633,60635,60647,60650,60652,60654,60656,60658-60659,60664-60666,60668-60670,60672,60676,60678,60680-60683,60685-60686,60688,60690,60692-60694,60697-60706,60708-60712,60714-60724 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r60701 | georg.brandl | 2008-02-09 22:36:15 +0100 (Sat, 09 Feb 2008) | 2 lines

  Needs only 2.4 now.
........
  r60702 | georg.brandl | 2008-02-09 22:38:54 +0100 (Sat, 09 Feb 2008) | 2 lines

  Docs are rst now.
........
  r60703 | georg.brandl | 2008-02-09 23:00:00 +0100 (Sat, 09 Feb 2008) | 2 lines

  Fix link.
........
  r60704 | georg.brandl | 2008-02-10 00:09:25 +0100 (Sun, 10 Feb 2008) | 2 lines

  Fix for newest doctools.
........
  r60709 | raymond.hettinger | 2008-02-10 08:21:09 +0100 (Sun, 10 Feb 2008) | 1 line

  Clarify that decimal also supports fixed-point arithmetic.
........
  r60710 | nick.coghlan | 2008-02-10 08:32:52 +0100 (Sun, 10 Feb 2008) | 1 line

  Add missing NEWS entry for r60695
........
  r60712 | mark.dickinson | 2008-02-10 15:58:38 +0100 (Sun, 10 Feb 2008) | 3 lines

  Turn classmethods into staticmethods, and avoid calling the constructor
  of subclasses of Rational.  (See discussion in issue #1682.)
........
  r60715 | mark.dickinson | 2008-02-10 16:19:58 +0100 (Sun, 10 Feb 2008) | 2 lines

  Typos in decimal comment and documentation
........
  r60716 | skip.montanaro | 2008-02-10 16:31:54 +0100 (Sun, 10 Feb 2008) | 2 lines

  Get the saying right. ;-)
........
  r60717 | skip.montanaro | 2008-02-10 16:32:16 +0100 (Sun, 10 Feb 2008) | 2 lines

  whoops - revert
........
  r60718 | mark.dickinson | 2008-02-10 20:23:36 +0100 (Sun, 10 Feb 2008) | 2 lines

  Remove reference to Rational
........
  r60719 | raymond.hettinger | 2008-02-10 21:35:16 +0100 (Sun, 10 Feb 2008) | 1 line

  Complete an open todo on pickletools -- add a pickle optimizer.
........
  r60721 | mark.dickinson | 2008-02-10 22:29:51 +0100 (Sun, 10 Feb 2008) | 3 lines

  Rename rational.Rational to fractions.Fraction, to avoid name clash
  with numbers.Rational.  See issue #1682 for related discussion.
........
  r60722 | christian.heimes | 2008-02-11 03:26:22 +0100 (Mon, 11 Feb 2008) | 1 line

  The test requires the network resource
........
  r60723 | mark.dickinson | 2008-02-11 04:11:55 +0100 (Mon, 11 Feb 2008) | 3 lines

  Put an extra space into the repr of a Fraction:
  Fraction(1, 2) instead of Fraction(1,2).
........
This commit is contained in:
Christian Heimes 2008-02-11 06:19:17 +00:00
parent ba99c58872
commit 3feef61742
15 changed files with 190 additions and 146 deletions

View File

@ -4,7 +4,6 @@ Complex.py Complex numbers
Dates.py Date manipulation package by Tim Peters
Dbm.py Wrapper around built-in dbm, supporting arbitrary values
Range.py Example of a generator: re-implement built-in range()
Rat.py Rational numbers
Rev.py Yield the reverse of a sequence
Vec.py A simple vector class
bitvec.py A bit-vector class by Jan-Hein B\"uhrman

View File

@ -14,7 +14,7 @@ those familiar with the previous docs written in LaTeX.
Building the docs
=================
You need to install Python 2.5.1 or higher (but Python 3.0 is not supported yet);
You need to install Python 2.4 or higher (but Python 3.0 is not supported yet);
the toolset used to build the docs are written in Python. The toolset used
to build the documentation is called *Sphinx*, it is not included in this
tree, but maintained separately in the Python Subversion repository. Also
@ -55,7 +55,7 @@ Available make targets are:
* "latex", which builds LaTeX source files that can be run with "pdflatex"
to produce PDF documents.
* "linkcheck", which checks all external references to see whether they are
broken, redirected or malformed, and outputs this information to stdout
as well as a plain-text (.txt) file.

View File

@ -38,17 +38,17 @@ today = ''
today_fmt = '%B %d, %Y'
# List of files that shouldn't be included in the build.
unused_files = [
'whatsnew/2.0.rst',
'whatsnew/2.1.rst',
'whatsnew/2.2.rst',
'whatsnew/2.3.rst',
'whatsnew/2.4.rst',
'whatsnew/2.5.rst',
'whatsnew/2.6.rst',
'maclib/scrap.rst',
'library/xmllib.rst',
'library/xml.etree.rst',
unused_docs = [
'whatsnew/2.0',
'whatsnew/2.1',
'whatsnew/2.2',
'whatsnew/2.3',
'whatsnew/2.4',
'whatsnew/2.5',
'whatsnew/2.6',
'maclib/scrap',
'library/xmllib',
'library/xml.etree',
]
# Relative filename of the reference count data file.

View File

@ -179,7 +179,7 @@ and add the following to the module initialization function::
MyObject_Type.ob_type = &PyType_Type;
Refer to section 3 of the `Python FAQ <http://www.python.org/doc/FAQ.html>`_ for
Refer to section 3 of the `Python FAQ <http://www.python.org/doc/faq>`_ for
details on why you must do this.

View File

@ -1,6 +1,6 @@
:mod:`decimal` --- Decimal floating point arithmetic
====================================================
:mod:`decimal` --- Decimal fixed point and floating point arithmetic
====================================================================
.. module:: decimal
:synopsis: Implementation of the General Decimal Arithmetic Specification.
@ -16,6 +16,11 @@
The :mod:`decimal` module provides support for decimal floating point
arithmetic. It offers several advantages over the :class:`float` datatype:
* Decimal "is based on a floating-point model which was designed with people
in mind, and necessarily has a paramount guiding principle -- computers must
provide an arithmetic that works in the same way as the arithmetic that
people learn at school." -- excerpt from the decimal arithmetic specification.
* Decimal numbers can be represented exactly. In contrast, numbers like
:const:`1.1` do not have an exact representation in binary floating point. End
users typically would not expect :const:`1.1` to display as
@ -25,7 +30,7 @@ arithmetic. It offers several advantages over the :class:`float` datatype:
+ 0.1 + 0.1 - 0.3`` is exactly equal to zero. In binary floating point, the result
is :const:`5.5511151231257827e-017`. While near to zero, the differences
prevent reliable equality testing and differences can accumulate. For this
reason, decimal would be preferred in accounting applications which have strict
reason, decimal is preferred in accounting applications which have strict
equality invariants.
* The decimal module incorporates a notion of significant places so that ``1.30
@ -50,6 +55,13 @@ arithmetic. It offers several advantages over the :class:`float` datatype:
standards. While the built-in float type exposes only a modest portion of its
capabilities, the decimal module exposes all required parts of the standard.
When needed, the programmer has full control over rounding and signal handling.
This includes an option to enforce exact arithmetic by using exceptions
to block any inexact operations.
* The decimal module was designed to support "without prejudice, both exact
unrounded decimal arithmetic (sometimes called fixed-point arithmetic)
and rounded floating-point arithmetic." -- excerpt from the decimal
arithmetic specification.
The module design is centered around three concepts: the decimal number, the
context for arithmetic, and signals.
@ -832,7 +844,7 @@ described below. In addition, the module provides three pre-made contexts:
:const:`ROUND_HALF_EVEN`. All flags are cleared. No traps are enabled (so that
exceptions are not raised during computations).
Because the trapped are disabled, this context is useful for applications that
Because the traps are disabled, this context is useful for applications that
prefer to have result value of :const:`NaN` or :const:`Infinity` instead of
raising exceptions. This allows an application to complete a run in the
presence of conditions that would otherwise halt the program.
@ -1245,7 +1257,7 @@ quiet or signaling :const:`NaN` always returns :const:`False` (even when doing
:const:`True`. An attempt to compare two Decimals using any of the ``<``,
``<=``, ``>`` or ``>=`` operators will raise the :exc:`InvalidOperation` signal
if either operand is a :const:`NaN`, and return :const:`False` if this signal is
trapped. Note that the General Decimal Arithmetic specification does not
not trapped. Note that the General Decimal Arithmetic specification does not
specify the behavior of direct comparisons; these rules for comparisons
involving a :const:`NaN` were taken from the IEEE 854 standard (see Table 3 in
section 5.7). To ensure strict standards-compliance, use the :meth:`compare`

View File

@ -1,28 +1,28 @@
:mod:`rational` --- Rational numbers
:mod:`fractions` --- Rational numbers
====================================
.. module:: rational
.. module:: fractions
:synopsis: Rational numbers.
.. moduleauthor:: Jeffrey Yasskin <jyasskin at gmail.com>
.. sectionauthor:: Jeffrey Yasskin <jyasskin at gmail.com>
.. versionadded:: 2.6
The :mod:`rational` module defines an immutable, infinite-precision
The :mod:`fractions` module defines an immutable, infinite-precision
Rational number class.
.. class:: Rational(numerator=0, denominator=1)
Rational(other_rational)
Rational(string)
.. class:: Fraction(numerator=0, denominator=1)
Fraction(other_fraction)
Fraction(string)
The first version requires that *numerator* and *denominator* are
instances of :class:`numbers.Integral` and returns a new
``Rational`` representing ``numerator/denominator``. If
``Fraction`` representing ``numerator/denominator``. If
*denominator* is :const:`0`, raises a :exc:`ZeroDivisionError`. The
second version requires that *other_rational* is an instance of
:class:`numbers.Rational` and returns an instance of
second version requires that *other_fraction* is an instance of
:class:`numbers.Fraction` and returns an instance of
:class:`Rational` with the same value. The third version expects a
string of the form ``[-+]?[0-9]+(/[0-9]+)?``, optionally surrounded
by spaces.
@ -31,39 +31,39 @@ Rational number class.
:class:`numbers.Rational` and is immutable and hashable.
.. method:: Rational.from_float(flt)
.. method:: Fraction.from_float(flt)
This classmethod constructs a :class:`Rational` representing the
This classmethod constructs a :class:`Fraction` representing the
exact value of *flt*, which must be a :class:`float`. Beware that
``Rational.from_float(0.3)`` is not the same value as ``Rational(3,
``Fraction.from_float(0.3)`` is not the same value as ``Rational(3,
10)``
.. method:: Rational.from_decimal(dec)
.. method:: Fraction.from_decimal(dec)
This classmethod constructs a :class:`Rational` representing the
This classmethod constructs a :class:`Fraction` representing the
exact value of *dec*, which must be a
:class:`decimal.Decimal`.
.. method:: Rational.__floor__()
.. method:: Fraction.__floor__()
Returns the greatest :class:`int` ``<= self``. Will be accessible
through :func:`math.floor` in Py3k.
.. method:: Rational.__ceil__()
.. method:: Fraction.__ceil__()
Returns the least :class:`int` ``>= self``. Will be accessible
through :func:`math.ceil` in Py3k.
.. method:: Rational.__round__()
Rational.__round__(ndigits)
.. method:: Fraction.__round__()
Fraction.__round__(ndigits)
The first version returns the nearest :class:`int` to ``self``,
rounding half to even. The second version rounds ``self`` to the
nearest multiple of ``Rational(1, 10**ndigits)`` (logically, if
nearest multiple of ``Fraction(1, 10**ndigits)`` (logically, if
``ndigits`` is negative), again rounding half toward even. Will be
accessible through :func:`round` in Py3k.

View File

@ -104,7 +104,7 @@ Notes for type implementors
Implementors should be careful to make equal numbers equal and hash
them to the same values. This may be subtle if there are two different
extensions of the real numbers. For example, :class:`rational.Rational`
extensions of the real numbers. For example, :class:`fractions.Fraction`
implements :func:`hash` as follows::
def __hash__(self):
@ -199,11 +199,11 @@ in :class:`complex`, and both :meth:`__radd__` s land there, so ``a+b
Because most of the operations on any given type will be very similar,
it can be useful to define a helper function which generates the
forward and reverse instances of any given operator. For example,
:class:`rational.Rational` uses::
:class:`fractions.Fraction` uses::
def _operator_fallbacks(monomorphic_operator, fallback_operator):
def forward(a, b):
if isinstance(b, (int, long, Rational)):
if isinstance(b, (int, long, Fraction)):
return monomorphic_operator(a, b)
elif isinstance(b, float):
return fallback_operator(float(a), b)
@ -215,7 +215,7 @@ forward and reverse instances of any given operator. For example,
forward.__doc__ = monomorphic_operator.__doc__
def reverse(b, a):
if isinstance(a, RationalAbc):
if isinstance(a, Rational):
# Includes ints.
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Real):
@ -231,7 +231,7 @@ forward and reverse instances of any given operator. For example,
def _add(a, b):
"""a + b"""
return Rational(a.numerator * b.denominator +
return Fraction(a.numerator * b.denominator +
b.numerator * a.denominator,
a.denominator * b.denominator)

View File

@ -33,3 +33,10 @@ probably won't find the :mod:`pickletools` module relevant.
the opcode's argument; *pos* is the position at which this opcode is located.
*pickle* can be a string or a file-like object.
.. function:: optimize(picklestring)
Returns a new equivalent pickle string after eliminating unused ``PUT``
opcodes. The optimized pickle is shorter, takes less transmission time,
requires less storage space, and unpickles more efficiently.
.. versionadded:: 2.6

View File

@ -578,8 +578,8 @@ and comparisons.
:class:`Rational` numbers derive from :class:`Real`, have
:attr:`numerator` and :attr:`denominator` properties, and can be
converted to floats. Python 2.6 adds a simple rational-number class
in the :mod:`rational` module.
converted to floats. Python 2.6 adds a simple rational-number class,
:class:`Fraction`, in the :mod:`fractions` module.
:class:`Integral` numbers derive from :class:`Rational`, and
can be shifted left and right with ``<<`` and ``>>``,
@ -598,29 +598,29 @@ one, :func:`trunc`, that's been backported to Python 2.6.
The Rational Module
The Fraction Module
--------------------------------------------------
To fill out the hierarchy of numeric types, a rational-number class
has been added as the :mod:`rational` module. Rational numbers are
has been added as the :mod:`fractions` module. Rational numbers are
represented as a fraction; rational numbers can exactly represent
numbers such as two-thirds that floating-point numbers can only
approximate.
The :class:`Rational` constructor takes two :class:`Integral` values
The :class:`Fraction` constructor takes two :class:`Integral` values
that will be the numerator and denominator of the resulting fraction. ::
>>> from rational import Rational
>>> a = Rational(2, 3)
>>> b = Rational(2, 5)
>>> from fractions import Fraction
>>> a = Fraction(2, 3)
>>> b = Fraction(2, 5)
>>> float(a), float(b)
(0.66666666666666663, 0.40000000000000002)
>>> a+b
rational.Rational(16,15)
Fraction(16, 15)
>>> a/b
rational.Rational(5,3)
Fraction(5, 3)
The :mod:`rational` module is based upon an implementation by Sjoerd
The :mod:`fractions` module is based upon an implementation by Sjoerd
Mullender that was in Python's :file:`Demo/classes/` directory for a
long time. This implementation was significantly updated by Jeffrey
Yaskin.

View File

@ -802,7 +802,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
# != comparisons involving a NaN always return True
# <, >, <= and >= comparisons involving a (quiet or signaling)
# NaN signal InvalidOperation, and return False if the
# InvalidOperation is trapped.
# InvalidOperation is not trapped.
#
# This behavior is designed to conform as closely as possible to
# that specified by IEEE 754.

View File

@ -1,16 +1,15 @@
# Originally contributed by Sjoerd Mullender.
# Significantly modified by Jeffrey Yasskin <jyasskin at gmail.com>.
"""Rational, infinite-precision, real numbers."""
"""Fraction, infinite-precision, real numbers."""
import math
import numbers
import operator
import re
__all__ = ["Rational"]
__all__ = ["Fraction"]
RationalAbc = numbers.Rational
def gcd(a, b):
@ -38,15 +37,15 @@ _RATIONAL_FORMAT = re.compile(r"""
""", re.VERBOSE)
class Rational(RationalAbc):
class Fraction(numbers.Rational):
"""This class implements rational numbers.
Rational(8, 6) will produce a rational number equivalent to
Fraction(8, 6) will produce a rational number equivalent to
4/3. Both arguments must be Integral. The numerator defaults to 0
and the denominator defaults to 1 so that Rational(3) == 3 and
Rational() == 0.
and the denominator defaults to 1 so that Fraction(3) == 3 and
Fraction() == 0.
Rationals can also be constructed from strings of the form
Fraction can also be constructed from strings of the form
'[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces.
"""
@ -61,7 +60,7 @@ class Rational(RationalAbc):
numerator/denominator pair.
"""
self = super(Rational, cls).__new__(cls)
self = super(Fraction, cls).__new__(cls)
if denominator == 1:
if isinstance(numerator, str):
@ -69,7 +68,7 @@ class Rational(RationalAbc):
input = numerator
m = _RATIONAL_FORMAT.match(input)
if m is None:
raise ValueError('Invalid literal for Rational: ' + input)
raise ValueError('Invalid literal for Fraction: ' + input)
numerator = m.group('num')
decimal = m.group('decimal')
if decimal:
@ -86,7 +85,7 @@ class Rational(RationalAbc):
numerator = -numerator
elif (not isinstance(numerator, numbers.Integral) and
isinstance(numerator, RationalAbc)):
isinstance(numerator, numbers.Rational)):
# Handle copies from other rationals.
other_rational = numerator
numerator = other_rational.numerator
@ -94,11 +93,11 @@ class Rational(RationalAbc):
if (not isinstance(numerator, numbers.Integral) or
not isinstance(denominator, numbers.Integral)):
raise TypeError("Rational(%(numerator)s, %(denominator)s):"
raise TypeError("Fraction(%(numerator)s, %(denominator)s):"
" Both arguments must be integral." % locals())
if denominator == 0:
raise ZeroDivisionError('Rational(%s, 0)' % numerator)
raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
g = gcd(numerator, denominator)
self._numerator = int(numerator // g)
@ -109,7 +108,7 @@ class Rational(RationalAbc):
def from_float(cls, f):
"""Converts a finite float to a rational number, exactly.
Beware that Rational.from_float(0.3) != Rational(3, 10).
Beware that Fraction.from_float(0.3) != Fraction(3, 10).
"""
if not isinstance(f, float):
@ -141,7 +140,7 @@ class Rational(RationalAbc):
@classmethod
def from_continued_fraction(cls, seq):
'Build a Rational from a continued fraction expessed as a sequence'
'Build a Fraction from a continued fraction expessed as a sequence'
n, d = 1, 0
for e in reversed(seq):
n, d = d, n
@ -168,7 +167,7 @@ class Rational(RationalAbc):
if self.denominator <= max_denominator:
return self
cf = self.as_continued_fraction()
result = Rational(0)
result = Fraction(0)
for i in range(1, len(cf)):
new = self.from_continued_fraction(cf[:i])
if new.denominator > max_denominator:
@ -186,7 +185,7 @@ class Rational(RationalAbc):
def __repr__(self):
"""repr(self)"""
return ('Rational(%r,%r)' % (self.numerator, self.denominator))
return ('Fraction(%r,%r)' % (self.numerator, self.denominator))
def __str__(self):
"""str(self)"""
@ -206,13 +205,13 @@ class Rational(RationalAbc):
that mixed-mode operations either call an implementation whose
author knew about the types of both arguments, or convert both
to the nearest built in type and do the operation there. In
Rational, that means that we define __add__ and __radd__ as:
Fraction, that means that we define __add__ and __radd__ as:
def __add__(self, other):
# Both types have numerators/denominator attributes,
# so do the operation directly
if isinstance(other, (int, Rational)):
return Rational(self.numerator * other.denominator +
if isinstance(other, (int, Fraction)):
return Fraction(self.numerator * other.denominator +
other.numerator * self.denominator,
self.denominator * other.denominator)
# float and complex don't have those operations, but we
@ -227,8 +226,8 @@ class Rational(RationalAbc):
def __radd__(self, other):
# radd handles more types than add because there's
# nothing left to fall back to.
if isinstance(other, RationalAbc):
return Rational(self.numerator * other.denominator +
if isinstance(other, numbers.Rational):
return Fraction(self.numerator * other.denominator +
other.numerator * self.denominator,
self.denominator * other.denominator)
elif isinstance(other, Real):
@ -239,32 +238,32 @@ class Rational(RationalAbc):
There are 5 different cases for a mixed-type addition on
Rational. I'll refer to all of the above code that doesn't
refer to Rational, float, or complex as "boilerplate". 'r'
will be an instance of Rational, which is a subtype of
RationalAbc (r : Rational <: RationalAbc), and b : B <:
Fraction. I'll refer to all of the above code that doesn't
refer to Fraction, float, or complex as "boilerplate". 'r'
will be an instance of Fraction, which is a subtype of
Rational (r : Fraction <: Rational), and b : B <:
Complex. The first three involve 'r + b':
1. If B <: Rational, int, float, or complex, we handle
1. If B <: Fraction, int, float, or complex, we handle
that specially, and all is well.
2. If Rational falls back to the boilerplate code, and it
2. If Fraction falls back to the boilerplate code, and it
were to return a value from __add__, we'd miss the
possibility that B defines a more intelligent __radd__,
so the boilerplate should return NotImplemented from
__add__. In particular, we don't handle RationalAbc
__add__. In particular, we don't handle Rational
here, even though we could get an exact answer, in case
the other type wants to do something special.
3. If B <: Rational, Python tries B.__radd__ before
Rational.__add__. This is ok, because it was
implemented with knowledge of Rational, so it can
3. If B <: Fraction, Python tries B.__radd__ before
Fraction.__add__. This is ok, because it was
implemented with knowledge of Fraction, so it can
handle those instances before delegating to Real or
Complex.
The next two situations describe 'b + r'. We assume that b
didn't know about Rational in its implementation, and that it
didn't know about Fraction in its implementation, and that it
uses similar boilerplate code:
4. If B <: RationalAbc, then __radd_ converts both to the
4. If B <: Rational, then __radd_ converts both to the
builtin rational type (hey look, that's us) and
proceeds.
5. Otherwise, __radd__ tries to find the nearest common
@ -276,7 +275,7 @@ class Rational(RationalAbc):
"""
def forward(a, b):
if isinstance(b, (int, Rational)):
if isinstance(b, (int, Fraction)):
return monomorphic_operator(a, b)
elif isinstance(b, float):
return fallback_operator(float(a), b)
@ -288,7 +287,7 @@ class Rational(RationalAbc):
forward.__doc__ = monomorphic_operator.__doc__
def reverse(b, a):
if isinstance(a, RationalAbc):
if isinstance(a, numbers.Rational):
# Includes ints.
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Real):
@ -304,7 +303,7 @@ class Rational(RationalAbc):
def _add(a, b):
"""a + b"""
return Rational(a.numerator * b.denominator +
return Fraction(a.numerator * b.denominator +
b.numerator * a.denominator,
a.denominator * b.denominator)
@ -312,7 +311,7 @@ class Rational(RationalAbc):
def _sub(a, b):
"""a - b"""
return Rational(a.numerator * b.denominator -
return Fraction(a.numerator * b.denominator -
b.numerator * a.denominator,
a.denominator * b.denominator)
@ -320,13 +319,13 @@ class Rational(RationalAbc):
def _mul(a, b):
"""a * b"""
return Rational(a.numerator * b.numerator, a.denominator * b.denominator)
return Fraction(a.numerator * b.numerator, a.denominator * b.denominator)
__mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul)
def _div(a, b):
"""a / b"""
return Rational(a.numerator * b.denominator,
return Fraction(a.numerator * b.denominator,
a.denominator * b.numerator)
__truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)
@ -357,14 +356,14 @@ class Rational(RationalAbc):
result will be rational.
"""
if isinstance(b, RationalAbc):
if isinstance(b, numbers.Rational):
if b.denominator == 1:
power = b.numerator
if power >= 0:
return Rational(a.numerator ** power,
return Fraction(a.numerator ** power,
a.denominator ** power)
else:
return Rational(a.denominator ** -power,
return Fraction(a.denominator ** -power,
a.numerator ** -power)
else:
# A fractional power will generally produce an
@ -379,8 +378,8 @@ class Rational(RationalAbc):
# If a is an int, keep it that way if possible.
return a ** b.numerator
if isinstance(a, RationalAbc):
return Rational(a.numerator, a.denominator) ** b
if isinstance(a, numbers.Rational):
return Fraction(a.numerator, a.denominator) ** b
if b.denominator == 1:
return a ** b.numerator
@ -388,16 +387,16 @@ class Rational(RationalAbc):
return a ** float(b)
def __pos__(a):
"""+a: Coerces a subclass instance to Rational"""
return Rational(a.numerator, a.denominator)
"""+a: Coerces a subclass instance to Fraction"""
return Fraction(a.numerator, a.denominator)
def __neg__(a):
"""-a"""
return Rational(-a.numerator, a.denominator)
return Fraction(-a.numerator, a.denominator)
def __abs__(a):
"""abs(a)"""
return Rational(abs(a.numerator), a.denominator)
return Fraction(abs(a.numerator), a.denominator)
def __trunc__(a):
"""trunc(a)"""
@ -433,12 +432,12 @@ class Rational(RationalAbc):
return floor + 1
shift = 10**abs(ndigits)
# See _operator_fallbacks.forward to check that the results of
# these operations will always be Rational and therefore have
# these operations will always be Fraction and therefore have
# round().
if ndigits > 0:
return Rational(round(self * shift), shift)
return Fraction(round(self * shift), shift)
else:
return Rational(round(self / shift) * shift)
return Fraction(round(self / shift) * shift)
def __hash__(self):
"""hash(self)
@ -461,7 +460,7 @@ class Rational(RationalAbc):
def __eq__(a, b):
"""a == b"""
if isinstance(b, RationalAbc):
if isinstance(b, numbers.Rational):
return (a.numerator == b.numerator and
a.denominator == b.denominator)
if isinstance(b, numbers.Complex) and b.imag == 0:
@ -488,7 +487,7 @@ class Rational(RationalAbc):
if isinstance(b, float):
b = a.from_float(b)
try:
# XXX: If b <: Real but not <: RationalAbc, this is likely
# XXX: If b <: Real but not <: Rational, this is likely
# to fall back to a float. If the actual values differ by
# less than MIN_FLOAT, this could falsely call them equal,
# which would make <= inconsistent with ==. Better ways of
@ -496,7 +495,7 @@ class Rational(RationalAbc):
diff = a - b
except TypeError:
return NotImplemented
if isinstance(diff, RationalAbc):
if isinstance(diff, numbers.Rational):
return op(diff.numerator, 0)
return op(diff, 0)
@ -526,11 +525,11 @@ class Rational(RationalAbc):
return (self.__class__, (str(self),))
def __copy__(self):
if type(self) == Rational:
if type(self) == Fraction:
return self # I'm immutable; therefore I am my own clone
return self.__class__(self.numerator, self.denominator)
def __deepcopy__(self, memo):
if type(self) == Rational:
if type(self) == Fraction:
return self # My components are also immutable
return self.__class__(self.numerator, self.denominator)

View File

@ -14,9 +14,7 @@ import codecs
import pickle
import re
__all__ = ['dis',
'genops',
]
__all__ = ['dis', 'genops', 'optimize']
bytes_types = pickle.bytes_types
@ -1835,6 +1833,33 @@ def genops(pickle):
assert opcode.name == 'STOP'
break
##############################################################################
# A pickle optimizer.
def optimize(p):
'Optimize a pickle string by removing unused PUT opcodes'
gets = set() # set of args used by a GET opcode
puts = [] # (arg, startpos, stoppos) for the PUT opcodes
prevpos = None # set to pos if previous opcode was a PUT
for opcode, arg, pos in genops(p):
if prevpos is not None:
puts.append((prevarg, prevpos, pos))
prevpos = None
if 'PUT' in opcode.name:
prevarg, prevpos = arg, pos
elif 'GET' in opcode.name:
gets.add(arg)
# Copy the pickle string except for PUTS without a corresponding GET
s = []
i = 0
for arg, start, stop in puts:
j = stop if (arg in gets) else start
s.append(p[i:j])
i = stop
s.append(p[i:])
return ''.join(s)
##############################################################################
# A symbolic pickle disassembler.

View File

@ -5,7 +5,7 @@ from test.test_support import fcmp, TESTFN, unlink, run_unittest, \
run_with_locale
from operator import neg
import sys, warnings, random, collections, io, rational
import sys, warnings, random, collections, io, rational, fractions
warnings.filterwarnings("ignore", "hex../oct.. of negative int",
FutureWarning, __name__)
warnings.filterwarnings("ignore", "integer argument expected",
@ -607,7 +607,7 @@ class BuiltinTest(unittest.TestCase):
n, d = f.as_integer_ratio()
self.assertEqual(float(n).__truediv__(d), f)
R = rational.Rational
R = fractions.Fraction
self.assertEqual(R(0, 1),
R(*float(0.0).as_integer_ratio()))
self.assertEqual(R(5, 2),

View File

@ -1,15 +1,15 @@
"""Tests for Lib/rational.py."""
"""Tests for Lib/fractions.py."""
from decimal import Decimal
from test.test_support import run_unittest, verbose
import math
import operator
import rational
import fractions
import unittest
from copy import copy, deepcopy
from pickle import dumps, loads
R = rational.Rational
gcd = rational.gcd
R = fractions.Fraction
gcd = fractions.gcd
class GcdTest(unittest.TestCase):
@ -31,7 +31,7 @@ def _components(r):
return (r.numerator, r.denominator)
class RationalTest(unittest.TestCase):
class FractionTest(unittest.TestCase):
def assertTypedEquals(self, expected, actual):
"""Asserts that both the types and values are the same."""
@ -60,7 +60,7 @@ class RationalTest(unittest.TestCase):
self.assertEquals((7, 15), _components(R(7, 15)))
self.assertEquals((10**23, 1), _components(R(10**23)))
self.assertRaisesMessage(ZeroDivisionError, "Rational(12, 0)",
self.assertRaisesMessage(ZeroDivisionError, "Fraction(12, 0)",
R, 12, 0)
self.assertRaises(TypeError, R, 1.5)
self.assertRaises(TypeError, R, 1.5 + 3j)
@ -81,41 +81,41 @@ class RationalTest(unittest.TestCase):
self.assertEquals((3, 5), _components(R(" .6 ")))
self.assertRaisesMessage(
ZeroDivisionError, "Rational(3, 0)",
ZeroDivisionError, "Fraction(3, 0)",
R, "3/0")
self.assertRaisesMessage(
ValueError, "Invalid literal for Rational: 3/",
ValueError, "Invalid literal for Fraction: 3/",
R, "3/")
self.assertRaisesMessage(
ValueError, "Invalid literal for Rational: 3 /2",
ValueError, "Invalid literal for Fraction: 3 /2",
R, "3 /2")
self.assertRaisesMessage(
# Denominators don't need a sign.
ValueError, "Invalid literal for Rational: 3/+2",
ValueError, "Invalid literal for Fraction: 3/+2",
R, "3/+2")
self.assertRaisesMessage(
# Imitate float's parsing.
ValueError, "Invalid literal for Rational: + 3/2",
ValueError, "Invalid literal for Fraction: + 3/2",
R, "+ 3/2")
self.assertRaisesMessage(
# Avoid treating '.' as a regex special character.
ValueError, "Invalid literal for Rational: 3a2",
ValueError, "Invalid literal for Fraction: 3a2",
R, "3a2")
self.assertRaisesMessage(
# Only parse ordinary decimals, not scientific form.
ValueError, "Invalid literal for Rational: 3.2e4",
ValueError, "Invalid literal for Fraction: 3.2e4",
R, "3.2e4")
self.assertRaisesMessage(
# Don't accept combinations of decimals and rationals.
ValueError, "Invalid literal for Rational: 3/7.2",
ValueError, "Invalid literal for Fraction: 3/7.2",
R, "3/7.2")
self.assertRaisesMessage(
# Don't accept combinations of decimals and rationals.
ValueError, "Invalid literal for Rational: 3.2/7",
ValueError, "Invalid literal for Fraction: 3.2/7",
R, "3.2/7")
self.assertRaisesMessage(
# Allow 3. and .3, but not .
ValueError, "Invalid literal for Rational: .",
ValueError, "Invalid literal for Fraction: .",
R, ".")
def testImmutable(self):
@ -136,7 +136,7 @@ class RationalTest(unittest.TestCase):
def testFromFloat(self):
self.assertRaisesMessage(
TypeError, "Rational.from_float() only takes floats, not 3 (int)",
TypeError, "Fraction.from_float() only takes floats, not 3 (int)",
R.from_float, 3)
self.assertEquals((0, 1), _components(R.from_float(-0.0)))
@ -152,19 +152,19 @@ class RationalTest(unittest.TestCase):
inf = 1e1000
nan = inf - inf
self.assertRaisesMessage(
TypeError, "Cannot convert inf to Rational.",
TypeError, "Cannot convert inf to Fraction.",
R.from_float, inf)
self.assertRaisesMessage(
TypeError, "Cannot convert -inf to Rational.",
TypeError, "Cannot convert -inf to Fraction.",
R.from_float, -inf)
self.assertRaisesMessage(
TypeError, "Cannot convert nan to Rational.",
TypeError, "Cannot convert nan to Fraction.",
R.from_float, nan)
def testFromDecimal(self):
self.assertRaisesMessage(
TypeError,
"Rational.from_decimal() only takes Decimals, not 3 (int)",
"Fraction.from_decimal() only takes Decimals, not 3 (int)",
R.from_decimal, 3)
self.assertEquals(R(0), R.from_decimal(Decimal("-0")))
self.assertEquals(R(5, 10), R.from_decimal(Decimal("0.5")))
@ -174,16 +174,16 @@ class RationalTest(unittest.TestCase):
R.from_decimal(Decimal("0." + "9" * 30)))
self.assertRaisesMessage(
TypeError, "Cannot convert Infinity to Rational.",
TypeError, "Cannot convert Infinity to Fraction.",
R.from_decimal, Decimal("inf"))
self.assertRaisesMessage(
TypeError, "Cannot convert -Infinity to Rational.",
TypeError, "Cannot convert -Infinity to Fraction.",
R.from_decimal, Decimal("-inf"))
self.assertRaisesMessage(
TypeError, "Cannot convert NaN to Rational.",
TypeError, "Cannot convert NaN to Fraction.",
R.from_decimal, Decimal("nan"))
self.assertRaisesMessage(
TypeError, "Cannot convert sNaN to Rational.",
TypeError, "Cannot convert sNaN to Fraction.",
R.from_decimal, Decimal("snan"))
def testFromContinuedFraction(self):
@ -316,7 +316,7 @@ class RationalTest(unittest.TestCase):
# Decimal refuses mixed comparisons.
self.assertRaisesMessage(
TypeError,
"unsupported operand type(s) for +: 'Rational' and 'Decimal'",
"unsupported operand type(s) for +: 'Fraction' and 'Decimal'",
operator.add, R(3,11), Decimal('3.1415926'))
self.assertNotEquals(R(5, 2), Decimal('2.5'))
@ -378,7 +378,7 @@ class RationalTest(unittest.TestCase):
self.assertFalse(R(5, 2) == 2)
def testStringification(self):
self.assertEquals("Rational(7,3)", repr(R(7, 3)))
self.assertEquals("Fraction(7,3)", repr(R(7, 3)))
self.assertEquals("7/3", str(R(7, 3)))
self.assertEquals("7", str(R(7, 1)))
@ -421,7 +421,7 @@ class RationalTest(unittest.TestCase):
self.assertEqual(id(r), id(deepcopy(r)))
def test_main():
run_unittest(RationalTest, GcdTest)
run_unittest(FractionTest, GcdTest)
if __name__ == '__main__':
test_main()

View File

@ -1182,6 +1182,8 @@ defdict_reduce(defdictobject *dd)
static PyMethodDef defdict_methods[] = {
{"__missing__", (PyCFunction)defdict_missing, METH_O,
defdict_missing_doc},
{"copy", (PyCFunction)defdict_copy, METH_NOARGS,
defdict_copy_doc},
{"__copy__", (PyCFunction)defdict_copy, METH_NOARGS,
defdict_copy_doc},
{"__reduce__", (PyCFunction)defdict_reduce, METH_NOARGS,