Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #46422 > unrolled thread
| Started by | Ma Xiaojun <damage3025@gmail.com> |
|---|---|
| First post | 2013-05-30 09:14 +0800 |
| Last post | 2013-06-01 04:52 +1000 |
| Articles | 11 — 6 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: How clean/elegant is Python's syntax? Ma Xiaojun <damage3025@gmail.com> - 2013-05-30 09:14 +0800
Re: How clean/elegant is Python's syntax? rusi <rustompmody@gmail.com> - 2013-05-29 19:49 -0700
Re: How clean/elegant is Python's syntax? Ian Kelly <ian.g.kelly@gmail.com> - 2013-05-30 12:36 -0600
Re: How clean/elegant is Python's syntax? rusi <rustompmody@gmail.com> - 2013-05-30 11:47 -0700
Re: How clean/elegant is Python's syntax? John Ladasky <john_ladasky@sbcglobal.net> - 2013-05-30 15:01 -0700
Re: How clean/elegant is Python's syntax? Chris Angelico <rosuav@gmail.com> - 2013-05-31 04:44 +1000
Re: How clean/elegant is Python's syntax? Ian Kelly <ian.g.kelly@gmail.com> - 2013-05-30 12:51 -0600
Re: How clean/elegant is Python's syntax? MRAB <python@mrabarnett.plus.com> - 2013-05-30 20:38 +0100
Re: How clean/elegant is Python's syntax? Chris Angelico <rosuav@gmail.com> - 2013-05-31 07:28 +1000
Re: How clean/elegant is Python's syntax? Ian Kelly <ian.g.kelly@gmail.com> - 2013-05-31 09:43 -0600
Re: How clean/elegant is Python's syntax? Chris Angelico <rosuav@gmail.com> - 2013-06-01 04:52 +1000
| From | Ma Xiaojun <damage3025@gmail.com> |
|---|---|
| Date | 2013-05-30 09:14 +0800 |
| Subject | Re: How clean/elegant is Python's syntax? |
| Message-ID | <mailman.2389.1369876474.3114.python-list@python.org> |
On Thu, May 30, 2013 at 8:24 AM, Dan Stromberg <drsalists@gmail.com> wrote: > I'm finding it kind of hard to imagine not finding Python's syntax and > semantics pretty graceful. > > About the only thing I don't like is: > > var = 1, > > That binds var to a tuple (singleton) value, instead of 1. > > Oh, and method decorators seem much more complex than they should've been. Yes, you touched something. IMHO, Python has far more built-in features so it looks at least complicated from time to time. For example, some people use "generating 9x9 multiplication table" as an programming exercise. What interest me is a one liner: print '\n'.join(['\t'.join(['%d*%d=%d' % (j,i,i*j) for i in range(1,10)]) for j in range(1,10)]) I don't like code like this. But Python at least allow such practise. > But on the whole, python is a pretty beautiful language. It's not just > another rehash of Pascal though; if that's what you want you might be better > off looking elsewhere. That's a fair point.
[toc] | [next] | [standalone]
| From | rusi <rustompmody@gmail.com> |
|---|---|
| Date | 2013-05-29 19:49 -0700 |
| Message-ID | <851ce96a-0223-42b0-8d99-902294c71f58@hc4g2000pbb.googlegroups.com> |
| In reply to | #46422 |
On May 30, 6:14 am, Ma Xiaojun <damage3...@gmail.com> wrote:
> What interest me is a one liner:
> print '\n'.join(['\t'.join(['%d*%d=%d' % (j,i,i*j) for i in
> range(1,10)]) for j in range(1,10)])
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')
> I don't like code like this. But Python at least allow such practise.
Are you saying VB etc disallow dirty code?? Dirty code is always
possible in all languages. Of course the shape and size and smell of
the dirt will differ
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2013-05-30 12:36 -0600 |
| Message-ID | <mailman.2443.1369939057.3114.python-list@python.org> |
| In reply to | #46425 |
On Wed, May 29, 2013 at 8:49 PM, rusi <rustompmody@gmail.com> wrote: > On May 30, 6:14 am, Ma Xiaojun <damage3...@gmail.com> wrote: >> What interest me is a one liner: >> print '\n'.join(['\t'.join(['%d*%d=%d' % (j,i,i*j) for i in >> range(1,10)]) for j in range(1,10)]) > > 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) I don't object to changing the join method (one of the more shoe-horned string methods) back into a function, but to my eyes you've got the arguments backward. It should be: def join(sep, iterable): return sep.join(iterable) Putting the separator first feels more natural to me because I expect the separator to usually be short as compared to the iterable, which is often a longer expression (as is the case in both of your subsequent usages). Placing the separator first also preserves consistency of interface with the str.join and bytes.join functions, as well as the older string.join function.
[toc] | [prev] | [next] | [standalone]
| From | rusi <rustompmody@gmail.com> |
|---|---|
| Date | 2013-05-30 11:47 -0700 |
| Message-ID | <0debce7e-f05c-40c4-b688-737e7ad49a40@z10g2000pbn.googlegroups.com> |
| In reply to | #46527 |
On May 30, 11:36 pm, Ian Kelly <ian.g.ke...@gmail.com> wrote:
> On Wed, May 29, 2013 at 8:49 PM, rusi <rustompm...@gmail.com> wrote:
> > On May 30, 6:14 am, Ma Xiaojun <damage3...@gmail.com> wrote:
> >> What interest me is a one liner:
> >> print '\n'.join(['\t'.join(['%d*%d=%d' % (j,i,i*j) for i in
> >> range(1,10)]) for j in range(1,10)])
>
> > 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)
>
> I don't object to changing the join method (one of the more
> shoe-horned string methods) back into a function, but to my eyes
> you've got the arguments backward. It should be:
>
> def join(sep, iterable): return sep.join(iterable)
>
> Putting the separator first feels more natural to me because I expect
> the separator to usually be short as compared to the iterable, which
> is often a longer expression (as is the case in both of your
> subsequent usages). Placing the separator first also preserves
> consistency of interface with the str.join and bytes.join functions,
> as well as the older string.join function.
This is a subjective view of course...
My problem is not method vs function but the order.
Ive seen/used join dozens of times. Yet I find
"".join(["apple","bear","cat"])
backkwards as compared to
["apple","bear","cat"].join("")
The consistency is a separate question -- not arguing about that. Just
that I dont like the look
[toc] | [prev] | [next] | [standalone]
| From | John Ladasky <john_ladasky@sbcglobal.net> |
|---|---|
| Date | 2013-05-30 15:01 -0700 |
| Message-ID | <32d47a30-8b74-41f4-a774-c878c60c7f73@googlegroups.com> |
| In reply to | #46527 |
On Thursday, May 30, 2013 11:36:54 AM UTC-7, Ian wrote: > I don't object to changing the join method (one of the more > shoe-horned string methods) back into a function, but to my eyes > you've got the arguments backward. It should be: > > def join(sep, iterable): return sep.join(iterable) > > Putting the separator first feels more natural to me because I expect > the separator to usually be short as compared to the iterable, which > is often a longer expression (as is the case in both of your > subsequent usages). Placing the separator first also preserves > consistency of interface with the str.join and bytes.join functions, > as well as the older string.join function. That may all be true, but the join() function shown will return a sequence starting with iterable[0] (followed by sep, and then iterable[1], then sep, etc.). I find it more natural to see iterable as the first argument passed to join() for that reason. Season to taste, I guess.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-05-31 04:44 +1000 |
| Message-ID | <mailman.2445.1369939485.3114.python-list@python.org> |
| In reply to | #46425 |
On Fri, May 31, 2013 at 4:36 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote: > On Wed, May 29, 2013 at 8:49 PM, rusi <rustompmody@gmail.com> wrote: >> On May 30, 6:14 am, Ma Xiaojun <damage3...@gmail.com> wrote: >>> What interest me is a one liner: >>> print '\n'.join(['\t'.join(['%d*%d=%d' % (j,i,i*j) for i in >>> range(1,10)]) for j in range(1,10)]) >> >> 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) > > I don't object to changing the join method (one of the more > shoe-horned string methods) back into a function, but to my eyes > you've got the arguments backward. It should be: > > def join(sep, iterable): return sep.join(iterable) Trouble is, it makes some sense either way. I often put the larger argument first - for instance, I would write 123412341324*5 rather than the other way around - and in this instance, it hardly seems as clear-cut as you imply. But the function can't be written to take them in either order, because strings are iterable too. (And functions that take args either way around aren't better than those that make a decision.) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2013-05-30 12:51 -0600 |
| Message-ID | <mailman.2446.1369939917.3114.python-list@python.org> |
| In reply to | #46425 |
On Thu, May 30, 2013 at 12:44 PM, Chris Angelico <rosuav@gmail.com> wrote: > On Fri, May 31, 2013 at 4:36 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote: >> I don't object to changing the join method (one of the more >> shoe-horned string methods) back into a function, but to my eyes >> you've got the arguments backward. It should be: >> >> def join(sep, iterable): return sep.join(iterable) > > Trouble is, it makes some sense either way. I often put the larger > argument first - for instance, I would write 123412341324*5 rather > than the other way around - and in this instance, it hardly seems as > clear-cut as you imply. But the function can't be written to take them > in either order, because strings are iterable too. (And functions that > take args either way around aren't better than those that make a > decision.) The reason I like having the shorter argument first (at least for function calls) is for when I'm reading the code. If I'm interested in the second argument, then to find it I have to scan over the first argument. I would rather scan over something short like '\n' than something longer like a list comprehension. It sounds like a trivial thing, but it really does make it easier to find where an expression starts and ends when the expression is short.
[toc] | [prev] | [next] | [standalone]
| From | MRAB <python@mrabarnett.plus.com> |
|---|---|
| Date | 2013-05-30 20:38 +0100 |
| Message-ID | <mailman.2448.1369942708.3114.python-list@python.org> |
| In reply to | #46425 |
On 30/05/2013 19:44, Chris Angelico wrote:
> On Fri, May 31, 2013 at 4:36 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote:
>> On Wed, May 29, 2013 at 8:49 PM, rusi <rustompmody@gmail.com> wrote:
>>> On May 30, 6:14 am, Ma Xiaojun <damage3...@gmail.com> wrote:
>>>> What interest me is a one liner:
>>>> print '\n'.join(['\t'.join(['%d*%d=%d' % (j,i,i*j) for i in
>>>> range(1,10)]) for j in range(1,10)])
>>>
>>> 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)
>>
>> I don't object to changing the join method (one of the more
>> shoe-horned string methods) back into a function, but to my eyes
>> you've got the arguments backward. It should be:
>>
>> def join(sep, iterable): return sep.join(iterable)
>
> Trouble is, it makes some sense either way. I often put the larger
> argument first - for instance, I would write 123412341324*5 rather
> than the other way around - and in this instance, it hardly seems as
> clear-cut as you imply. But the function can't be written to take them
> in either order, because strings are iterable too. (And functions that
> take args either way around aren't better than those that make a
> decision.)
>
And additional argument (pun not intended) for putting sep second is
that you can give it a default value:
def join(iterable, sep=""): return sep.join(iterable)
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-05-31 07:28 +1000 |
| Message-ID | <mailman.2453.1369949301.3114.python-list@python.org> |
| In reply to | #46425 |
On Fri, May 31, 2013 at 4:51 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote: > On Thu, May 30, 2013 at 12:44 PM, Chris Angelico <rosuav@gmail.com> wrote: >> On Fri, May 31, 2013 at 4:36 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote: >>> I don't object to changing the join method (one of the more >>> shoe-horned string methods) back into a function, but to my eyes >>> you've got the arguments backward. It should be: >>> >>> def join(sep, iterable): return sep.join(iterable) >> >> Trouble is, it makes some sense either way. I often put the larger >> argument first - for instance, I would write 123412341324*5 rather >> than the other way around - and in this instance, it hardly seems as >> clear-cut as you imply. But the function can't be written to take them >> in either order, because strings are iterable too. (And functions that >> take args either way around aren't better than those that make a >> decision.) > > The reason I like having the shorter argument first (at least for > function calls) is for when I'm reading the code. If I'm interested > in the second argument, then to find it I have to scan over the first > argument. I would rather scan over something short like '\n' than > something longer like a list comprehension. It sounds like a trivial > thing, but it really does make it easier to find where an expression > starts and ends when the expression is short. Yes, I do agree with that argument. But there's more to picking argument order than simply "sort by predicted length" :) I'm not saying it's *wrong* to put sep first, just that it's not as clearly-and-obviously-the-one-right-way as you suggested. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2013-05-31 09:43 -0600 |
| Message-ID | <mailman.2493.1370015077.3114.python-list@python.org> |
| In reply to | #46425 |
On Thu, May 30, 2013 at 1:38 PM, MRAB <python@mrabarnett.plus.com> wrote: > And additional argument (pun not intended) for putting sep second is > that you can give it a default value: > > def join(iterable, sep=""): return sep.join(iterable) One argument against the default is that it is specific to the str type. If you then tried to use join with an iterable of bytes objects and the default sep argument, you would get a TypeError. At least not having the default forces you to be explicit about which string type you're joining.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-06-01 04:52 +1000 |
| Message-ID | <mailman.2501.1370026382.3114.python-list@python.org> |
| In reply to | #46425 |
On Sat, Jun 1, 2013 at 1:43 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote:
> On Thu, May 30, 2013 at 1:38 PM, MRAB <python@mrabarnett.plus.com> wrote:
>> And additional argument (pun not intended) for putting sep second is
>> that you can give it a default value:
>>
>> def join(iterable, sep=""): return sep.join(iterable)
>
> One argument against the default is that it is specific to the str
> type. If you then tried to use join with an iterable of bytes objects
> and the default sep argument, you would get a TypeError. At least not
> having the default forces you to be explicit about which string type
> you're joining.
What about:
def join(iterable, sep=None):
if sep is not None: return sep.join(iterable)
iterable=iter(iterable)
first = next(iterable)
return first + type(first)().join(iterable)
Granted, it has some odd error messages if you pass it stuff that isn't strings:
>>> join([[1,2,3],[4,5,6]])
Traceback (most recent call last):
File "<pyshell#241>", line 1, in <module>
join([[1,2,3],[4,5,6]])
File "<pyshell#235>", line 5, in join
return first + type(first)().join(iterable)
AttributeError: 'list' object has no attribute 'join'
but you'd get that sort of thing anyway.
(NOTE: I am *not* advocating this. I just see it as a solution to one
particular objection.)
ChrisA
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web