'%s' % 100000 được đánh giá bởi trình biên dịch và tương đương với một hằng số tại thời điểm chạy.
>>> import dis
>>> dis.dis(lambda: str(100000))
  8           0 LOAD_GLOBAL              0 (str)
              3 LOAD_CONST               1 (100000)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE        
>>> dis.dis(lambda: '%s' % 100000)
  9           0 LOAD_CONST               3 ('100000')
              3 RETURN_VALUE        
%với biểu thức thời gian chạy không nhanh hơn (đáng kể) so với str:
>>> Timer('str(x)', 'x=100').timeit()
0.25641703605651855
>>> Timer('"%s" % x', 'x=100').timeit()
0.2169809341430664
Xin lưu ý rằng strtốc độ vẫn chậm hơn một chút, như @DietrichEpp đã nói, điều này là do strliên quan đến thao tác tra cứu và gọi hàm, trong khi %biên dịch thành một mã bytecode duy nhất ngay lập tức:
>>> dis.dis(lambda x: str(x))
  9           0 LOAD_GLOBAL              0 (str)
              3 LOAD_FAST                0 (x)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE        
>>> dis.dis(lambda x: '%s' % x)
 10           0 LOAD_CONST               1 ('%s')
              3 LOAD_FAST                0 (x)
              6 BINARY_MODULO       
              7 RETURN_VALUE        
Tất nhiên điều trên đúng với hệ thống tôi đã thử nghiệm (CPython 2.7); các triển khai khác có thể khác.
     
              
'{}'.format(100000)