How clean/elegant is Python's syntax?

rusi rustompmody at gmail.com
Thu May 30 13:12:22 EDT 2013


On Thu, May 30, 2013 at 9:34 AM, Ma Xiaojun <damage3025 at gmail.com>
wrote:
>
> On Thu, May 30, 2013 at 10:49 AM, rusi <rustompmody at gmail.com> wrote:
> > Ha,Ha! The join method is one of the (for me) ugly features of python.
> > You can sweep it under the carpet with a one-line join function and
> > then write clean and pretty code:
> >
> > #joinwith
> > def joinw(l,sep): return sep.join(l)
> >
> > def mktable(m,n):
> >     return [[(j,i,i*j) for i in range(1,m+1)] for j in range(1,n+1)]
> >
> > def prettyrow(r):
> >     return joinw(['%d*%d=%d' % ele for ele in r],'\t')
> >
> > def prettytable(t):
> >     return joinw([prettyrow(r) for r in t],'\n')
>
> Wait a minute! Isn't the most nature way of doing/thinking "generating
> 9x9 multiplication table" two nested loop?

Thats like saying that the most natur(al) way of using a car is to
attach a horse to it.
Sure if all you've seen are horse-carriages then a horseless carriage
will seem nonsensical.  Once you get used to horseless carriages the
horsed ones would seem quite a nuisance [global warming aside!!]

The only problem with this analogy is that you have to imagine the
world of horse/horseless 'cars' in 1900 and not 2013.

Likewise in the world of programming, 90% of programmers think
imperative/OO programming is natural while functional programming is
strange.  Just wait 10 years and see if things are not drastically
different!

>
> I understand that using "join", we don't need to worry about "one
> element doesn't need white space" issue. And that's it.

More evidence of the above!
join like list-comprehensions are tools for functional programming and
not merely ways of writing loops in short.

The key difference between the two is seen not in the code you write
but in the natural language (English) you use to describe it:

> Wait a minute! Isn't the most nature way of doing/thinking "generating
> 9x9 multiplication table" two nested loop?

You associate the primal (f)act of thinking about programming with
*doing* the generating.
By contrast the functional programmer thinks about what *is* the
result.

Please also note the difference in emphasis in your code and mine.
Rewriting to make it more obvious:

# The main multiplication table building function
def multtable(m,n):
    return [[(j,i,i*j) for i in range(1,m+1)] for j in range(1,n+1)]

# The 'icing' to get it into the shape you want
def joinw(l,sep): return sep.join(l)
def prettytable(t):
    return joinw([joinw(['%d*%d=%d' % ele for ele in r],'\t') for r in
t],'\n')

The call that puts them together:
>>> print prettytable(multtable(6,7))

The nice thing about the last is that it separates three things:
1. Computing the actual table
2. The string form of that table that looks the way we want
3. Printing that string

And I can see each of these separately:

In [2]: multtable(2,3)
Out[2]: [[(1, 1, 1), (1, 2, 2)], [(2, 1, 2), (2, 2, 4)], [(3, 1, 3),
(3, 2, 6)]]

In [3]: prettytable(_)
Out[3]: '1*1=1\t1*2=2\n2*1=2\t2*2=4\n3*1=3\t3*2=6'

In [4]: print _
1*1=1	1*2=2
2*1=2	2*2=4
3*1=3	3*2=6

-------------------
I would be pleasantly surprised if the double nested loop you think
natural, allowed for such a modular separation!



More information about the Python-list mailing list