Почему это 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
объекте, а не на других итерациях.
-
объявляет, что вы присоединяетесь к списку и конвертируете в строку. Она ориентирована на результат.