Можете ли вы описать разницу между двумя способами конкатенации строк: простым оператором __add__ и шаблонами %s? Я изучил этот вопрос и обнаружил, что %s (в форме без скобок) немного быстрее.

Также возник другой вопрос: почему результат 'hell%s' % 'o' относится к другой области памяти, чем 'hell%s' % ('o',)?

Вот пример кода:

l = ['hello', 'hell' + 'o', 'hell%s' % 'o', 'hell%s' % ('o',)]
print [id(s) for s in l]

Результат:

[34375618400, 34375618400, 34375618400, 34375626256]

P.S. Я знаю про интернирование струн :)

3
Roman Bodnarchuk 30 Июл 2010 в 17:14

2 ответа

Лучший ответ

Вот небольшое упражнение:

>>> def f1():
    'hello'


>>> def f2():
    'hel' 'lo'


>>> def f3():
    'hel' + 'lo'


>>> def f4():
    'hel%s' % 'lo'


>>> def f5():
    'hel%s' % ('lo',)


>>> for f in (f1, f2, f3, f4, f5):
    print(f.__name__)
    dis.dis(f)


f1
  1           0 LOAD_CONST               1 (None) 
              3 RETURN_VALUE         
f2
  1           0 LOAD_CONST               1 (None) 
              3 RETURN_VALUE         
f3
  2           0 LOAD_CONST               3 ('hello') 
              3 POP_TOP              
              4 LOAD_CONST               0 (None) 
              7 RETURN_VALUE         
f4
  2           0 LOAD_CONST               3 ('hello') 
              3 POP_TOP              
              4 LOAD_CONST               0 (None) 
              7 RETURN_VALUE         
f5
  2           0 LOAD_CONST               1 ('hel%s') 
              3 LOAD_CONST               3 (('lo',)) 
              6 BINARY_MODULO        
              7 POP_TOP              
              8 LOAD_CONST               0 (None) 
             11 RETURN_VALUE         

Как видите, все простые конкатенации / форматирование выполняется компилятором. Последняя функция требует более сложного форматирования и поэтому, я думаю, фактически выполняется. Поскольку все эти объекты, созданные во время компиляции, все имеют одинаковый идентификатор.

7
SilentGhost 30 Июл 2010 в 13:25

С технической точки зрения использование % является строковым форматированием , а не конкатенацией. Это два совершенно * разных мира.

Если вы знаете об интернировании строк, вы должны знать, что нет абсолютно никакой гарантии, что две строки будут занимать ту же память, что и другая. Тот факт, что в вашем примере действуют первые три, - не более чем чистое совпадение.

Я не уверен на 100%, как работает форматирование строк, но я знаю, что в базовом C оно не реализовано так же, как конкатенация - я думаю, что это работает немного больше по принципу ''.join(sequence), что также быстрее, чем + для больших строк - см. этот пост для получения дополнительной информации.

*вроде.

1
Community 23 Май 2017 в 12:27