Чому це string.join(list)
замість list.join(string)
?
Це тому join
, що це "рядковий" метод! Він створює рядок з будь-якого ітерабельного. Якщо ми закріпили метод у списках, що робити, коли у нас є ітерабелі, які не є списками?
Що робити, якщо у вас є кортеж струн? Якби це list
метод, вам слід було б передати кожен такий ітератор рядків як a, 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'
Продуктивність Caveat для генераторів
Алгоритм, який 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
об'єкті, ніж на різних ітерабелях.
-
заявляєте, що ви приєднуєтесь до списку та переходите на рядок. Орієнтований на результат.