[Python-Dev] trunc() (original) (raw)

Guido van Rossum guido at python.org
Sun Jan 27 17:43:14 CET 2008


On Jan 26, 2008 11:14 PM, Raymond Hettinger <python at rcn.com> wrote:

>. You may disagree, but that doesn't make it nuts.

Too many thoughts compressed into one adjective ;-) [snip]

> I don't think that Excel should be held up as a shining example for > Python.

It is simply a datapoint. [snip]

You're beginning to repeat your argument; none of that was new.

One other thought: In Python, it has been nice that we have simple type coercions using the type name: * set(p)-->q can accept a list, tuple, string, or any iterable and make a set * int(p)-->q can accept an int, long, float, or string and make an int * float(p)-->q can accept an int, long, float, or string and make an int * list(p)-->q can accept a list, tuple, string, or any iterable and make a list * unicode(p)--> can accept a str, buffer, or unicode object and make a unicode object It's a bit weird to decide that int() needs to lose that capability so we get generalized Integrals as output. What's wrong with coercion to a concrete type?

Let me get back to you on that.

I first want to point out that you snipped the core of my argument in the post you otherwise quoted. I will repeat it here because I would like your explicit reaction:

[Guido]

There is actually quite an important signal to the reader that is present when you see trunc(x) but absent when you see int(x): with trunc(x), the implication is that x is a (Real) number. With int(x), you can make no such assumption -- x could be a string, or it could be a totally different type that happens to define int, perhaps a custom date/time type (I believe mxDateTime supports this).

Can I assume that you agree with this? That would be progress.

Coming back to your argument that other types have a constructor that takes all kinds of arguments, I'd like to point out that they all have restrictions too (except for str()): list() and tuple() only accept iterables, float() only accepts strings and certain numbers (not complex), and so on. Taking the latter as an example:

float(0j) Traceback (most recent call last): File "", line 1, in TypeError: can't convert complex to float; use abs(z)

I think that (eventually) int(0.0) could do something similar:

int(0.0) Traceback (most recent call last): File "", line 1, in TypeError: can't convert float to int; use round(x) or trunc(x)

But see below.

Yet another (minor) argument that has always made me uncomfortable with int() == trunc(): the % operator. I think it's a big improvement over C that Python's % operator is defined as

x%y == x - y*floor(x/y) # where / is real division

rather than C's division, which uses trunc() instead of floor(). In C this nicely meshes with the definition of int(): you can define x%y as x - y*(int)(x/y); but not so in Python. I don't want to use this as an argument for defining int(x) as floor(x), but I do want to point out that it has always given me a twinge of discomfort.

FInally, there's the "one way" argument. That's a nice slogan, but doesn't really hold anyways in practice. To copy a list, we can write either L[:] or list(L). To get the keys of a dict, we can write either D.keys() or list(D). To convert a number to a string we can write either "%g" % X or str(X). For octal we can write "%#o" % X or oct(X). To convert a unicode string to UTF-8, we can write either U.encode("utf8") or str(U, "utf8"). And so on. In many cases, these notations aren't exactly the same in semantics (e.g. list(X) always returns a list, X[:] returns whatever sequence type X is), but nevertheless they have large areas of overlap. This is how I see trunc() and int() live together.

After all that, here's my current proposal:

-- --Guido van Rossum (home page: http://www.python.org/~guido/)



More information about the Python-Dev mailing list