dis
полезен, например, когда другой код выполняет одно и то же и вам интересно, в чем заключается разница в производительности.
Пример: list += [item]
против list.append(item)
def f(x): return 2*x
def f1(func, nums):
result = []
for item in nums:
result += [fun(item)]
return result
def f2(func, nums):
result = []
for item in nums:
result.append(fun(item))
return result
timeit.timeit
говорит, что f2(f, range(100))
примерно в два раза быстрее, чем f1(f, range(100)
. Почему?
(Интересно, что f2
примерно такой же быстрый, как map(f, range(100))
.)
f1
Вы можете увидеть весь вывод dis, вызвав dis.dis(f1)
, вот строка 4.
4 19 LOAD_FAST 2 (result)
22 LOAD_FAST 1 (fun)
25 LOAD_FAST 3 (item)
28 CALL_FUNCTION 1
31 BUILD_LIST 1
34 INPLACE_ADD
35 STORE_FAST 2 (result)
38 JUMP_ABSOLUTE 13
>> 41 POP_BLOCK
f2
Опять же, здесь только строка 4:
4 19 LOAD_FAST 2 (result)
22 LOAD_ATTR 0 (append)
25 LOAD_FAST 1 (fun)
28 LOAD_FAST 3 (item)
31 CALL_FUNCTION 1
34 CALL_FUNCTION 1
37 POP_TOP
38 JUMP_ABSOLUTE 13
>> 41 POP_BLOCK
Найди разницу
В f1
нам нужно:
- Звоните
fun
на item
(код операции 28)
- Составьте из него список (код операции 31, дорого!)
- Добавить к
result
(код операции 34)
- Сохранить возвращаемое значение в
result
(код операции 35)
В f2
вместо этого мы просто:
- Звоните
fun
на item
(код операции 31)
- Звоните
append
на result
(код операции 34; код C: быстро!)
Это объясняет, почему (imho) более выразительный list += [value]
намного медленнее, чем list.append()
метод.
Кроме этого, dis.dis
в основном полезен для любопытства и для попытки восстановить код из .pyc
файлов, у которых нет источника, не потратив целое состояние:)