why isn't a decimal an instance of the real number abstract base class? [duplicate]

  • Last Update :
  • Techknowledgy :

Answer is in numbers module source:

# # Notes on Decimal
# #-- -- -- -- -- -- -- --
# # Decimal has all of the methods specified by the Real abc, but it should
# # not be registered as a Real because decimals do not interoperate with
# # binary floats(i.e.Decimal('3.14') + 2.71828 is undefined).But,
   # # abstract reals are expected to interoperate(i.e.R1 + R2 should be # # expected to work
      if R1 and R2 are both Reals).

Suggestion : 2

The python Decimal object is not currently anycodings_python specified a subclass of the Real abstract anycodings_python base class:,Answer is in numbers module source:,But it makes me ask the question: why is anycodings_python Decimal not registered this way to begin anycodings_python with? Is there some practical reason, or anycodings_python design reason, that it would be a bad idea anycodings_python to make this assumption about decimal anycodings_python instances?,This is easily changed by registering anycodings_python Decimal as a subclass:

The python Decimal object is not currently anycodings_python specified a subclass of the Real abstract anycodings_python base class:

from numbers
import Real
from decimal
import Decimal

isinstance(Decimal("1.0"), numbers.Real) # False

This is easily changed by registering anycodings_python Decimal as a subclass:

Real.register(Decimal)

Answer is in numbers module source:

# # Notes on Decimal
# #-- -- -- -- -- -- -- --
# # Decimal has all of the methods specified by the Real abc, but it should
# # not be registered as a Real because decimals do not interoperate with
# # binary floats(i.e.Decimal('3.14') + 2.71828 is undefined).But,
   # # abstract reals are expected to interoperate(i.e.R1 + R2 should be # # expected to work
      if R1 and R2 are both Reals).

Suggestion : 3

The numbers module (PEP 3141) defines a hierarchy of numeric abstract base classes which progressively define more operations. None of the types defined in this module are intended to be instantiated.,numbers — Numeric abstract base classes The numeric tower Notes for type implementors Adding More Numeric ABCs Implementing the arithmetic operations ,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, fractions.Fraction uses:,numbers — Numeric abstract base classes

def __hash__(self):
   if self.denominator == 1:
   # Get integers right.
return hash(self.numerator)
# Expensive check, but definitely correct.
if self == float(self):
   return hash(float(self))
else:
   # Use tuple 's hash to avoid a high collision rate on
# simple fractions.
return hash((self.numerator, self.denominator))
class MyFoo(Complex): ...
   MyFoo.register(Real)
class MyIntegral(Integral):

   def __add__(self, other):
   if isinstance(other, MyIntegral):
   return do_my_adding_stuff(self, other)
elif isinstance(other, OtherTypeIKnowAbout):
   return do_my_other_adding_stuff(self, other)
else:
   return NotImplemented

def __radd__(self, other):
   if isinstance(other, MyIntegral):
   return do_my_adding_stuff(other, self)
elif isinstance(other, OtherTypeIKnowAbout):
   return do_my_other_adding_stuff(other, self)
elif isinstance(other, Integral):
   return int(other) + int(self)
elif isinstance(other, Real):
   return float(other) + float(self)
elif isinstance(other, Complex):
   return complex(other) + complex(self)
else:
   return NotImplemented
def _operator_fallbacks(monomorphic_operator, fallback_operator):
   def forward(a, b):
   if isinstance(b, (int, Fraction)):
   return monomorphic_operator(a, b)
elif isinstance(b, float):
   return fallback_operator(float(a), b)
elif isinstance(b, complex):
   return fallback_operator(complex(a), b)
else:
   return NotImplemented
forward.__name__ = '__' + fallback_operator.__name__ + '__'
forward.__doc__ = monomorphic_operator.__doc__

def reverse(b, a):
   if isinstance(a, Rational):
   # Includes ints.
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Real):
   return fallback_operator(float(a), float(b))
elif isinstance(a, numbers.Complex):
   return fallback_operator(complex(a), complex(b))
else:
   return NotImplemented
reverse.__name__ = '__r' + fallback_operator.__name__ + '__'
reverse.__doc__ = monomorphic_operator.__doc__

return forward, reverse

def _add(a, b):
   ""
"a + b"
""
return Fraction(a.numerator * b.denominator +
   b.numerator * a.denominator,
   a.denominator * b.denominator)

__add__, __radd__ = _operator_fallbacks(_add, operator.add)

#...

Suggestion : 4

Type is not to be used. It’s nearly never the proper answer in Python because it disables polymorphism’s flexibility. If you subclass int, for example, your new class should register as an int, which is not the case:,If you truly need to inspect anything, abstract base classes are preferable to concrete ones. For an integer, this means:,This mindset is gradually being replaced by the use of abstract base classes, which allow you to specify exactly what properties your object should have (adding? multiplying? doubling?) by inheriting from a specially-constructed class. That would be the greatest approach because it will allow just those objects having the required and adequate properties, but you’ll have to read the documentation to figure out how to utilize it.,This corresponds to Python’s strong polymorphism: instead of requiring that an object act like an int, you should let any object that behaves like one.

If you have to do this,

isinstance(<var>, int)

Unless you’re using Python 2.x, in which case you should use

isinstance(<var>, (int, long))

Type is not to be used. It’s nearly never the proper answer in Python because it disables polymorphism’s flexibility. If you subclass int, for example, your new class should register as an int, which is not the case:

class Spam(int): pass
x = Spam(0)
type(x) == int # False
isinstance(x, int) # True

In a for loop, an example of what to perform every xth time is:

for index in range(y):
   # do something
   if (index / x.).is_integer():
      # do something special

Before calling this method, you can always convert to a float. The three options are:

>>> float(5).is_integer()
True
   >>>
   float(5.1).is_integer()
False
   >>>
   float(5.0).is_integer()
True

Suggestion : 5

Both binary and decimal floating point are implemented in terms of published 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.,Both binary and decimal floating point are implemented in terms of published 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 makes it possible to restore the identities by expanding the precision sufficiently to avoid loss of significance:,In accordance with the standard, the Decimal module provides two ready to use standard contexts, BasicContext and ExtendedContext. The former is especially useful for debugging because many of the traps are enabled:

>>> getcontext().prec = 6 >>>
   Decimal(1) / Decimal(7)
Decimal('0.142857') >>>
   getcontext().prec = 28 >>>
   Decimal(1) / Decimal(7)
Decimal('0.1428571428571428571428571429')
>>> from decimal
import *
>>>
getcontext()
Context(prec = 28, rounding = ROUND_HALF_EVEN, Emin = -999999999, Emax = 999999999,
   capitals = 1, flags = [], traps = [Overflow, DivisionByZero,
      InvalidOperation
   ])
>>> getcontext().prec = 7 # Set a new precision
>>> getcontext().prec = 28 >>>
   Decimal(10)
Decimal('10') >>>
   Decimal('3.14')
Decimal('3.14') >>>
   Decimal((0, (3, 1, 4), -2))
Decimal('3.14') >>>
   Decimal(str(2.0 ** 0.5))
Decimal('1.41421356237') >>>
   Decimal(2) ** Decimal('0.5')
Decimal('1.414213562373095048801688724') >>>
   Decimal('NaN')
Decimal('NaN') >>>
   Decimal('-Infinity')
Decimal('-Infinity')
>>> getcontext().prec = 6 >>>
   Decimal('3.0')
Decimal('3.0') >>>
   Decimal('3.1415926535')
Decimal('3.1415926535') >>>
   Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987') >>>
   getcontext().rounding = ROUND_UP >>>
   Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')
>>> data = map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()) >>>
   max(data)
Decimal('9.25') >>>
   min(data)
Decimal('0.03') >>>
   sorted(data)[Decimal('0.03'), Decimal('1.00'), Decimal('1.34'), Decimal('1.87'),
      Decimal('2.35'), Decimal('3.45'), Decimal('9.25')] >>>
   sum(data)
Decimal('19.29') >>>
   a, b, c = data[: 3] >>>
   str(a)
'1.34' >>>
float(a)
1.3400000000000001
   >>>
   round(a, 1) # round() first converts to binary floating point
1.3
   >>>
   int(a)
1
   >>>
   a * 5
Decimal('6.70') >>>
   a * b
Decimal('2.5058') >>>
   c % a
Decimal('0.77')

Suggestion : 6

Groovy supports different kinds of integral literals and decimal literals, backed by the usual Number types of Java.,1.1.5. Numbers Integral literals Alternative non-base 10 representations Binary literal Octal literal Hexadecimal literal Decimal literals Underscore in literals Number type suffixes Math operations The case of the division operator The case of the power operator ,This type hint supports a single signature and each of the parameter is specified as a value of the options array using a fully-qualified type name or a primitive type.,There are numerous helper classes that simplify many testing activities. The details differ in some cases depending on the version of JUnit you are using. We’ll cover those details shortly.

// a standalone single line comment
println "hello" // a comment till the end of the line
/* a standalone multiline comment
   spanning two lines */
println "hello"
/* a multiline comment starting
                  at the end of a statement */
println 1 /* one */ + 2 /* two */
/**
 * A Class description
 */
class Person {
   /** the name of the person */
   String name

   /**
    * Creates a greeting method for a certain person.
    *
    * @param otherPerson the person to greet
    * @return a greeting message
    */
   String greet(String otherPerson) {
      "Hello ${otherPerson}"
   }
}
/**@
 * Some class groovydoc for Foo
 */
class Foo {
   /**@
    * Some method groovydoc for bar
    */
   void bar() {}
}

assert Foo.class.groovydoc.content.contains('Some class groovydoc for Foo')(1)
assert Foo.class.getMethod('bar', new Class[0]).groovydoc.content.contains('Some method groovydoc for bar')(2)
#!/usr/bin/env groovy

println "Hello from the shebang line"
// reserved keywords can be used for method names if quoted
def "abstract"() {
   true
}
// when calling such methods, the name must be qualified using "this."
this.abstract()