Python's numeric tower

Discussion in 'Python' started by Steven D'Aprano, Jun 15, 2014.

  1. Does anyone know any examples of values or types from the standard
    library or well-known third-party libraries which satisfies
    isinstance(a, numbers.Number) but not isinstance(a, numbers.Complex)?
    Steven D'Aprano, Jun 15, 2014
    1. Advertisements

  2. Steven D'Aprano

    Ian Kelly Guest

    Ian Kelly, Jun 15, 2014
    1. Advertisements

  3. Well, that surprises and disappoints me, but thank you for the answer.
    Steven D'Aprano, Jun 15, 2014
  4. Steven D'Aprano

    Roy Smith Guest

    Why would you expect Decimal to be a subclass of Complex?
    Roy Smith, Jun 15, 2014
  5. Steven D'Aprano

    Ian Kelly Guest

    One might expect it for the same reason that float is a subclass of
    Complex. Decimal was intentionally excluded from the numeric tower
    (as noted in PEP 3141), but apparently it still subclasses Number. As
    I understand it the reason Decimal was excluded was because it doesn't
    fully implement the methods of Complex; for example, given two Complex
    instances, one expects to be able to add them, but that doesn't always
    hold for Decimal depending on the type of the other operand:
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'

    The Number ast doesn't specify any particular behavior and is there to
    "to make it easy for people to be fuzzy about what kind of number they
    expect", so I guess the developers so no harm in letting Decimal
    subclass it.
    Ian Kelly, Jun 15, 2014

  6. py> from decimal import Decimal
    py> Decimal("1.5").imag

    Mathematically, â„‚ (complex) is a superset of â„ (real), and Decimals are a
    kind of real(ish) number, like float:

    py> from numbers import Complex
    py> isinstance(1.5, Complex)

    But then I suppose it is understandable that Decimal doesn't support the
    full range of complex arithmetic.
    Steven D'Aprano, Jun 16, 2014
  7. The Python complex type represents a subset of â„‚. The Python Decimal
    and float types implement a subset of â„, which as you say is a subset
    of ℂ. The Python int type implements a subset of ℤ. (Although if you
    have infinite storage, you could theoretically represent all of ℤ with
    int, and possibly all of â„ with Decimal. But I don't know of any
    Python implementation that can utilize infinite RAM.)

    The question isn't really about the mathematical number sets, but
    about what operations you can do. The numbers.Complex type specifies

    class Complex(Number)
    | Complex defines the operations that work on the builtin complex type.
    | In short, those are: a conversion to complex, .real, .imag, +, -,
    | *, /, abs(), .conjugate, ==, and !=.
    *as long as you work exclusively with Decimal*. You can check their
    ..real and .imag (.imag will be Decimal('0'), and .real is self), you
    can conjugate them (returns self), and you can do arithmetic with
    them. But you can't mix complex and decimal, any more than you can mix
    float and decimal:
    Traceback (most recent call last):
    File "<pyshell#30>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'Traceback (most recent call last):
    File "<pyshell#31>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'complex'

    Ergo, currently, you can't say that decimal.Decimal can be treated as
    a complex. (Although you can call complex(d) and get back a meaningful
    value, within the limits of precision - again, same as with float(d).)

    To contrast, numbers.Number places very few requirements on its
    subclasses. And decimal.Decimal isn't a subclass of any of the rest of
    the tower:
    Number - True
    Complex - False
    Real - False
    Rational - False
    Integral - False

    As I understand it, isinstance(x,numbers.Complex) should be True for
    anything that you can treat like a complex() - that is, that you can
    add it to a complex(), do operations on it, etc, etc, etc. I'm not
    sure what isinstance(x,numbers.Number) promises in terms of usability;
    I guess if you have a list of Numbers that are all the same type, you
    can probably sum them, but you can sum non-Numbers too. The docstring
    is a bit vague - sure, it's a number, but what can you do with it?

    Chris Angelico, Jun 16, 2014
  8. Steven D'Aprano

    Roy Smith Guest

    You can use it to count to three!
    Roy Smith, Jun 16, 2014
  9. Since "increment" is not a provided method, and the + and += operators
    are not guaranteed to be defined for any definition of 1 on the other
    side, I'm not sure that's actually true... but if you hold a hand
    grenade and want to know whether to count to Decimal('3') or 3+0j or
    Fraction(3, 1), I'm just going to tell you to throw the thing already!

    Chris Angelico, Jun 16, 2014
  10. Steven D'Aprano

    Roy Smith Guest

    I don't believe HandGrenade implements throw(). It does, however,
    implement lobbeth().
    Roy Smith, Jun 16, 2014
  11. Steven D'Aprano

    Roy Smith Guest

    On second thought, it probably implements lob(). You can, however
    derive lobbeth() by calling conjugate().
    Roy Smith, Jun 16, 2014
  12. The above looks like a bug that should have been picked up, why hasn't
    OverflowError been raised?
    Mark Lawrence, Jun 16, 2014
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.