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