Tuesday, December 18, 2007

(NOT) Bitten by PEP 3113

UPDATE: The comments left on this post (1 and 3) in particular corrected my misreading of PEP 3113. There is no such wart as I describe in Python 3.0. I should have known better than to question GvR and friends. :-) I'm leaving this post as a reference.

In trying to make Crunchy useful & interesting for beginning programmers to learn Python, I designed a small graphics library following some "natural" notation. As an aside, Johannes Woolard is the one who made sure that this library could be easily used interactively within Crunchy. I mention his name since too many people seem to assume that I am the only one involved in Crunchy's design. Anyway, back to the library...

In that library, the function used to draw a line between two points uses the syntax

line((x1, y1), (x2, y2))

for example: line((100, 100), (200, 200))


which should be familiar to everyone. Unfortunately, following the implementation of PEP 3113 in Python 3.0, this syntax is no longer allowed. This is ... annoying! There are two alternatives I can use:

line(x1, y1, x2, y2)

for example: line(100, 100, 200, 200)


or

line(point_1, point_2)

where point_a = (x_a, y_a). Update: with this second definition, it will be possible to invoke the function as
line((100, 100), (200, 200))

Of course, either of these two option is easy to implement (and is going to be backward compatible with Python 2k). However, I don't find either one of them particularly clear for beginners (who might be familiar with the normal mathematical notation) and do not consider this a (small) wart of Python 3k.

4 comments:

Alex said...

Only tuple unpacking in function arguments has been deprecated; you can of course still pass two tuples as arguments to a function. For example,

def line((x1, y1), (x2, y2)):
# ...

can be rewritten:

def line(p1, p2):
x1, y1 = p1
x2, y2 = p2
# ...

the user API does not change.

André said...

Alex:

I realize this - I gave that as the second alternative. However, it means that a user calling the line function would have to do

p1 = (100, 100)
p2 = (200, 200)
line(p1, p2)

which is not as "simple" as simply writing
line((100, 100), (200, 200))

Alex said...

I'm think you're mistaken:

>>> def line(p1, p2):
... x1, y1 = p1
... x2, y2 = p2
... print x1, y1, x2, y2
...
>>> line((100, 100), (200, 200))
100 100 200 200
>>>

Josh said...

In line with Alex, reading PEP3113 closely, under the "No Loss of Abilities If Removed" heading, states that you can still pass in tuples, they just can't be unpacked automatically.