Ошибки округления с плавающей запятой. 0,1 не могут быть представлены точно в базе-2, как в базе-10, из-за недостающего простого коэффициента 5. Так же, как 1/3 принимает бесконечное число цифр для представления в десятичной форме, но составляет «0,1» в базе-3, 0.1 принимает бесконечное число цифр в базе-2, где оно не находится в базе-10. И компьютеры не имеют бесконечного объема памяти.
Лучший способ добавления строки к строковой переменной - использовать +
или +=
. Это потому, что оно читаемо и быстро. Они также так же быстро, что вы выбираете, это вопрос вкуса, последний из них наиболее распространен. Ниже приведены тайминги с модулем timeit
:
a = a + b:
0.11338996887207031
a += b:
0.11040496826171875
Однако те, кто рекомендует иметь списки и присоединяться к ним, а затем присоединяются к этим спискам, делают это, потому что добавление строки в список, по-видимому, очень быстро по сравнению с расширением строки. И это может быть правдой, в некоторых случаях. Вот, например, один миллион добавлений односимвольной строки, сначала к строке, а затем к списку:
a += b:
0.10780501365661621
a.append(b):
0.1123361587524414
ОК, оказывается, что даже когда результирующая строка составляет миллион символов
Теперь попробуем с добавлением строки длиной в тысячу символов сто тысяч раз:
a += b:
0.41823482513427734
a.append(b):
0.010656118392944336
Конечная строка, следовательно, заканчивается примерно 100 МБ длинный. Это было довольно медленно, добавление к списку было намного быстрее. То, что время не включает окончательный a.join()
. Так как долго это займет?
a.join(a):
0.43739795684814453
Oups. Оказывается даже в этом случае, добавление / объединение происходит медленнее.
Итак, откуда эта рекомендация? Python 2?
a += b:
0.165287017822
a.append(b):
0.0132720470428
a.join(a):
0.114929914474
Ну, append / join является незначительно быстрее там, если вы используете чрезвычайно длинные строки (которых обычно нет, что бы у вас была строка это 100 МБ в памяти?)
Но настоящим клинчером является Python 2.3. Где я даже не покажу вам тайминги, потому что это так медленно, что он еще не закончил. Эти тесты внезапно вызывают минуты . За исключением append / join, что так же быстро, как и при последующих Python.
Yup. Конкатенация строк была очень медленной в Python в каменном веке. Но на 2.4 это уже не (или, по крайней мере, Python 2.4.7), поэтому рекомендация использовать append / join устарела в 2008 году, когда Python 2.3 перестает быть обновленным, и вы должны прекратить ее использовать. : -)
(Обновление: Оказывается, когда я тщательно тестировал, что использование +
и +=
выполняется быстрее для двух строк на Python 2.3. Рекомендация использовать ''.join()
должно быть недоразумением)
Однако это CPython. Другие реализации могут иметь другие проблемы. И это еще одна причина, почему преждевременная оптимизация - это корень всего зла. Не используйте метод, который предполагается «быстрее», если вы его не измерили.
Поэтому «лучшей» версией для выполнения конкатенации строк является использование + или + =. И если это окажется для вас медленным, что маловероятно, тогда сделайте что-нибудь еще.
Итак, почему я использую много добавления / присоединения в моем коде? Потому что иногда это на самом деле яснее. Особенно, когда все, что вы должны объединить вместе, должно быть разделено пробелами или запятыми или символами новой строки.
Вы можете использовать это (более эффективное) тоже. ( https://softwareengineering.stackexchange.com/questions/304445/why-is-s-better-than-for-concatenation )
s += "%s" %(stringfromelsewhere)
Использование конкатенации строк на месте с помощью '+' - это метод СОВМЕСТИМОСТИ конкатенации с точки зрения стабильности и кросс-реализации, поскольку он не поддерживает все значения. Стандарт PEP8 обескураживает это и поощряет использование format (), join () и append () для долгосрочного использования.
мой случай использования был немного другим. Мне пришлось построить запрос, в котором более 20 полей были динамическими. Я следовал этому методу использования метода format
query = "insert into {0}({1},{2},{3}) values({4}, {5}, {6})"
query.format('users','name','age','dna','suzan',1010,'nda')
, это было сравнительно проще для меня вместо использования + или других способов
Если вы объединяете множество значений, то ни то, ни другое. Добавление списка дорого. Вы можете использовать StringIO для этого. Особенно если вы создаете его для большого количества операций.
from cStringIO import StringIO
# python3: from io import StringIO
buf = StringIO()
buf.write('foo')
buf.write('foo')
buf.write('foo')
buf.getvalue()
# 'foofoofoo'
Если у вас уже есть полный список, возвращенный вам из какой-либо другой операции, просто используйте ''.join(aList)
Из часто задаваемых вопросов python: Каков наиболее эффективный способ объединить многие строки вместе?
Объекты str и байты неизменяемы, поэтому объединение нескольких строк вместе неэффективно поскольку каждая конкатенация создает новый объект. В общем случае общая стоимость исполнения равна квадрату в общей длине строки.
Чтобы скопировать много объектов str, рекомендуемая идиома состоит в том, чтобы поместить их в список и вызвать str.join () в конце :
chunks = [] for s in my_strings: chunks.append(s) result = ''.join(chunks)
(другая разумно эффективная идиома заключается в использовании io.StringIO)
Чтобы скопировать много объектов с байтами, рекомендуемая идиома заключается в расширении объекта bytearray с использованием конкатенации на месте (оператор + =):
blockquote>result = bytearray() for b in my_bytes_objects: result += b
Редактирование: я был глупым и имел результаты, вставленные назад, заставляя его выглядеть как добавление в список быстрее cStringIO. Я также добавил тесты для bytearray / str concat, а также второй раунд тестов, используя более крупный список с большими строками. (python 2.7.3)
Пример тестирования ipython для больших списков строк
try: from cStringIO import StringIO except: from io import StringIO source = ['foo']*1000 %%timeit buf = StringIO() for i in source: buf.write(i) final = buf.getvalue() # 1000 loops, best of 3: 1.27 ms per loop %%timeit out = [] for i in source: out.append(i) final = ''.join(out) # 1000 loops, best of 3: 9.89 ms per loop %%timeit out = bytearray() for i in source: out += i # 10000 loops, best of 3: 98.5 µs per loop %%timeit out = "" for i in source: out += i # 10000 loops, best of 3: 161 µs per loop ## Repeat the tests with a larger list, containing ## strings that are bigger than the small string caching ## done by the Python source = ['foo']*1000 # cStringIO # 10 loops, best of 3: 19.2 ms per loop # list append and join # 100 loops, best of 3: 144 ms per loop # bytearray() += # 100 loops, best of 3: 3.8 ms per loop # str() += # 100 loops, best of 3: 5.11 ms per loop
Хотя несколько датировано, Код Как и Pythonista: Idiomatic Python рекомендует join()
по +
в этом разделе . Как и PythonSpeedPerformanceTips в своем разделе в конкатенации строки со следующим отказом:
Точность этого раздела оспаривается относительно более позднего версии Python. В CPython 2.5 конкатенация строк довольно быстрая, хотя это может не совпадать с другими реализациями Python. См. ConcatenationTestCode для обсуждения.
blockquote>
Рекомендуемый метод по-прежнему использовать append и join.
Вы записываете эту функцию
def str_join(*args):
return ''.join(map(str, args))
Затем вы можете звонить просто, где хотите
str_join('Pine') # Returns : Pine
str_join('Pine', 'apple') # Returns : Pineapple
str_join('Pine', 'apple', 3) # Returns : Pineapple3
В Python> = 3.6 новая f-строка является эффективным способом конкатенации строки.
>>> name = 'some_name'
>>> number = 123
>>>
>>> f'Name is {name} and the number is {number}.'
'Name is some_name and the number is 123.'