On Sun, Oct 21, 2012 at 11:53 AM, Steven D'Aprano <st...@pearwood.info> wrote: > On 21/10/12 06:28, Tres Seaver wrote: >> >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA1 >> >> On 10/19/2012 07:35 PM, Greg Ewing wrote: >>> >>> Antonio Cuni wrote: >>>> >>>> Traceback (most recent call last): File "<stdin>", line 1, in >>>> <module> TypeError: __complex__ should return a complex object >>>> >>>> i.e., the complex constructor does not check that __complex__ >>>> returns an actual complex, while the cmath functions do. >>> >>> >>> Looks to me like cmath is being excessively finicky here. Why >>> shouldn't a float be usable in *any* context expecting a complex? >> >> >> Exactly: float is perfectly Liskov-substituable for complex; only >> applications which do explicit type sniffing can tell the difference, >> which makes the sniffing bogus. > > > > But float is not *numerically* substitutable for complex, which is why > type-sniffing is not bogus at all. If you have an application which > assumes numeric quantities represent real values, then you need to > distinguish between real-valued and complex-valued arithmetic, and > treating floats as implicitly complex is the wrong thing to do. > > Since most applications are based on real-values, implicit promotion to > complex is in my opinion an anti-feature. > > Python 2.x legitimately distinguished between floats and complex, e.g.: > > py> (-100.0)**0.5 > > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > ValueError: negative number cannot be raised to a fractional power > > If you wanted a complex result, you can explicitly ask for one: > > py> (-100.0+0j)**0.5 > (6.123031769111886e-16+10j) > > > I see that behaviour is changed in Python 3. Was this discussed before > being changed? I see a single sample docstring buried in PEP 3141 that: > > """a**b; should promote to float or complex when necessary.""" > > but I can't find any discussion of the consequences of this for the > majority of users who would be surprised by the unexpected appearance > of a "j" inside their numbers.
PEP 3141 is indeed the driver for these changes, and it's based on the Python 3.x numeric tower consisting of strict supersets: Complex > Real > Rational > Integral If an operation at one level of the tower produces a result in one of the larger supersets, then *that's what it will do* rather than throwing TypeError. int / int promoting to float is one example, as is raising a negative number to a fractional power promoting to complex. The general philosophy is described in http://www.python.org/dev/peps/pep-3141/#implementing-the-arithmetic-operations It sounds like cmath (or, more specifically, the "D" conversion code) missed out on the associated updates). Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com