Hacker News new | past | comments | ask | show | jobs | submit login

The whole point of having join() as a method on the string is that it is meant to handle any kind of iterator. You can join a list, a generator, or the custom iterator of your choice. In any of those cases, it looks the same and is implemented only once.

If join() was not a string method then it would have to belong in some mixin that you slap onto your iterators, and that increases code complexity.

Also, you can do things like map(operator.methodcaller("capitalize"), iterator_of_strings), but that is probably bad style.

And in Ruby you can do your_object.method("foo") to turn your method into a lambda.




Sounds to me like join would work better as a function ;)


See the design FAQ here: http://docs.python.org/faq/design.html#why-is-join-a-string-...

Admittedly, the join syntax is somewhat counter-intuitive and arguably ugly, but it does the job without defining new built-in functions or adding extra syntax. If you really can't stand the syntax, you can always do this:

    # old style way of joining strings
    import string
    string.join([1,2,3], ' ')
or:

    str.join(' ', [1,2,3])
Of course method #1 requires importing an extra module (which can be a bit of a pain) and method #2 requires knowing more about python's implementation of str (as you argued about using str.capitalize), but they work. Generally though, the syntax isn't that bad, but you have alternatives if you want them.


$ipython

In [1]: x = [1,2,3]

In [2]: y = [4,5,6]

In [3]: x + y

Out[3]: [1, 2, 3, 4, 5, 6]

Why use 6 [join()] characters when you can use 1 :)


Polymorphism.


Except that it only makes sense in the context of strings, so it makes perfect sense to make it a string method.


It seems to me like join makes sense in any context where you have multiple elements that you want joined. With strings, you happen to have a separator. But you might also want to join several lists into one flattened list. (Edit: I know there are ways to do this. The point is that join could be unified around this concept.)

Even if you disagree, the line between methods and functions in Python really isn't standardized.


You can join several lists into a flattened list as well:

reduce(operator.add, list_of_lists)

You can not say sum(), sadly, because it forces a restriction that you only sum numbers.


It's not pretty, but you can do it:

  >>> sum([['a', 'b', 'c'], ['d', 'e', 'f']], [])
  ['a', 'b', 'c', 'd', 'e', 'f']
This makes use of the optional start argument and list add operator. However, Python's docs suggest using itertools.chain instead:

http://docs.python.org/library/functions.html#sum

  >>> import itertools
  >>> [l for l in itertools.chain(*[['a', 'b', 'c'], ['d', 'e', 'f']])]
  ['a', 'b', 'c', 'd', 'e', 'f']
(Of course you lose the benefit of a generator by using a list comprehension, but this is just an example.)


Your second example is easier to just write as:

  >>> from itertools import chain
  >>> list_of_lists = [['a', 'b', 'c'], ['d', 'e', 'f']]
  >>> list(chain(*list_of_lists))
  ['a', 'b', 'c', 'd', 'e', 'f']
That is, list(«foo») is clearer and more idiomatic than [x for x in «foo»].


I may be missing something, but why isn't skipping your list comprehension maintaining the benefit of using a generator?

   >>> from itertools import chain
   >>> chain(*[['a', 'b', 'c'], ['d', 'e', 'f']])


It is, but I don't get to show you the result of the chain that way. :)




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: