Почему это string.join(list)
вместо list.join(string)
?
Это потому, что join
является "строковым" методом! Создает строку из любого итератора. Если мы поместим метод в списки, что делать, когда у нас есть итерации, которые не являются списками?
Что если у вас есть набор строк? Если бы это был метод list
, вам бы пришлось приводить каждый такой итератор строк как list
, прежде чем вы могли бы объединить элементы в одну строку! Например:
some_strings = ('foo', 'bar', 'baz')
Давайте свернем наш собственный метод соединения со списком:
class OurList(list):
def join(self, s):
return s.join(self)
И чтобы использовать его, обратите внимание, что мы должны сначала создать список из каждой итерации, чтобы объединить строки в эту итерацию, тратя при этом как память, так и мощность процессора:
>>> l = OurList(some_strings) # step 1, create our list
>>> l.join(', ') # step 2, use our list join method!
'foo, bar, baz'
Итак, мы видим, что мы должны добавить дополнительный шаг, чтобы использовать наш метод списка, вместо того, чтобы просто использовать метод встроенной строки:
>>> ' | '.join(some_strings) # a single step!
'foo | bar | baz'
Предупреждение о производительности для генераторов
Алгоритм, который Python использует для создания окончательной строки с str.join
, на самом деле должен дважды передавать итеративное значение, поэтому, если вы предоставите ему выражение генератора, он должен сначала материализовать его в список, прежде чем сможет создать окончательную строку ,
Таким образом, хотя обход генераторов обычно лучше, чем списки, str.join
является исключением:
>>> import timeit
>>> min(timeit.repeat(lambda: ''.join(str(i) for i in range(10) if i)))
3.839168446022086
>>> min(timeit.repeat(lambda: ''.join([str(i) for i in range(10) if i])))
3.339879313018173
Тем не менее, операция str.join
все еще семантически является «строковой» операцией, поэтому все же имеет смысл иметь ее на объекте str
, чем на других итерациях.