Mark Dickinson <dicki...@gmail.com> added the comment:

[Mark]
> inputs with a special real or imaginary component.  On balance, I'd 
> support making complex('nan + nan*j') do the right thing.

Having thought about this a bit more, I take this back.  Some reasons are 
given below.

[David]
> - complex(repr(..)) roundtrip should work, whatever the value of complex 
is

I disagree. *Why* do you think it should work?  It fails for many other 
types:

>>> def roundtrip(x): return type(x)(repr(x))
... 
>>> roundtrip("abc")
"'abc'"
>>> roundtrip([1,2,3])
['[', '1', ',', ' ', '2', ',', ' ', '3', ']']
>>> roundtrip((1,))
('(', '1', ',', ')')
>>> roundtrip(Fraction(1, 2))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in roundtrip
  File "/Users/dickinsm/python_source/trunk/Lib/fractions.py", line 73, in 
__new__
    raise ValueError('Invalid literal for Fraction: %r' % input)
ValueError: Invalid literal for Fraction: 'Fraction(1, 2)'
>>> roundtrip(Decimal(1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in roundtrip
  File "/Users/dickinsm/python_source/trunk/Lib/decimal.py", line 545, in 
__new__
    "Invalid literal for Decimal: %r" % value)
  File "/Users/dickinsm/python_source/trunk/Lib/decimal.py", line 3721, in 
_raise_error
    raise error(explanation)
decimal.InvalidOperation: Invalid literal for Decimal: "Decimal('1')"


In general, type(repr(x)) == x only works for simple types (ints, floats), 
not compound types like lists, strings, tuples, ...  I think it's 
reasonable to regard complex as such a compound type.

There *is* a general Python guideline that eval(repr(x)) == x should work 
where possible.  Note that this fails even for floats:

>>> eval(repr(float('nan')))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'nan' is not defined


The *real* problem here is that repr(complex) is a mess when it comes to 
niceties like signed zeros, infinities and nans:

>>> complex(-0., 0.)  # throws away sign of 0 on real part
0j
>>> eval(repr(complex(2., -0.)))  # throws away sign on imag. part
(2+0j)
>>> nan = float('nan')
>>> complex(0, nan)
nan*j
>>> nan*j  # can't even eval this...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'j' is not defined
>>> nan*1j # not much better: real part should be 0, not nan
(nan+nan*j)
>>> inf = float('inf')
>>> inf*1j  # ouch: nan in real part!
(nan+inf*j)


I think the *right* solution is to define repr of a complex number
z to be:

"complex(%r, %r)" % (z.real, z.imag)

but that's not possible before the mythical, compatibility-breaking, 
Python 4.0.  And even then your desired complex(repr(z)) roundtripping 
wouldn't work, though eval(repr(z)) would.

While we're daydreaming, another possibility is to follow C99's lead, and 
introduce a type of 'imaginary' numbers, and make 1j be an imaginary 
literal rather than a complex literal.  That solves some of the above 
eval(repr(.)) problems.  Again, I don't see how this could happen before 
4.0, and I'm not even sure that it's desirable.

In the circumstances, repr does the best it can, which is to output a 
whole expression which more-or-less describes the given complex number, 
and will usually eval back to the right thing.  I think it's not the 
business of the complex() constructor to parse such expressions.

To summarize:  it's a mess.  I'd recommend that you and/or numpy don't use 
repr for roundtrip-capable conversions to string.  Instead, output the 
real and imaginary parts separately, and use float-from-string and the 
complex-from-pair-of-floats constructors to reconstruct.

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue2121>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to