#98 PgNumeric += is strange

open
nobody
PgNumeric (6)
5
2007-07-17
2007-07-17
Ken Lalonde
No

The augmented arithmetic operations on PgNumeric instances will update the object directly,
instead of creating a new one.
This leads to unexpected results such as:

$ cat t.py
from pyPgSQL.PgSQL import PgNumeric
a = PgNumeric(1.0)
b = a
b += 1
print a, b
$ python t.py
2.0 2.0

Here we see b is incremented, but both a and b
are changed, because the __iadd__ method updates
b in place.

Call me naive, but I would expect "b += 1"
to behave exactly like "b = b+1".

Perhaps PgNumeric should allocate a new object
if the old one has multiple references?
I'm not sure, but the current behavior
is not intuitive, and leads to hard-to-find bugs.

Discussion

  • Logged In: YES
    user_id=2014513
    Originator: NO

    IMHO you are right, it's worse, this bug affects not only '+='. See this:

    >>> ZERO = PgSQL.PgNumeric('0')
    >>> a = ZERO; b = ZERO; b = b + 1; c = ZERO
    >>> print ZERO,a,b,c
    0 0 1 0
    >>> a = ZERO; b = ZERO; b += 1; c = ZERO
    >>> print ZERO,a,b,c
    1 1 1 1
    >>> ZERO = PgSQL.PgNumeric('0')
    >>> a = ZERO; b = ZERO; b = b - 1; c = ZERO
    >>> print ZERO,a,b,c
    0 0 -1 0
    >>> a = ZERO; b = ZERO; b -= 1; c = ZERO
    >>> print ZERO,a,b,c
    -1 -1 -1 -1
    >>> TWO = PgSQL.PgNumeric('2')
    >>> a = TWO; b = TWO; b = b * 3; c = TWO
    >>> print TWO,a,b,c
    2 2 6 2
    >>> a = TWO; b = TWO; b *= 3; c = TWO
    >>> print TWO,a,b,c
    6 6 6 6
    >>> TWO = PgSQL.PgNumeric('2')
    >>> a = TWO; b = TWO; b = b / 2; c = TWO
    >>> print TWO,a,b,c
    2 2 1 2
    >>> a = TWO; b = TWO; b /= 2; c = TWO
    >>> print TWO,a,b,c
    1 1 1 1

    Regards,
    Pietro