Подводные камни использования изменяемых типов в функциях Python
Использование изменяемых типов данных в аргументах Python функций обернется головной болью для начинающего программиста. В то же время знание особенностей работы с ними можно обратить в свою пользу путем задания гибкого поведения определяемых методов.
Так, изменяемый тип создается в момент объявления функции и модифицируется при каждом обращении к ней (конечно, если в теле это предусмотрено). Объявим функцию и вызовем ее с разными аргументами:
def f(a, l=[]): l.append(a) return l
f(1)
f(2)
Как можно заметить, второй вызов привел к выводу списка, включающего оба элемента (1 и 2).
Такое поведение изменяемых типов иногда полезно использовать. Например, мы можем задать локальный кэш для своих данных, когда операции их получения трудоемки. Снова объявим функцию:
def cache_op(a,b, cache={}): if (a,b) in cache: res = cache[(a,b)] else: res = a**b cache[(a,b)] = res return res
Далее вызовем ее дважды с одними и теми же аргументами и замерим скорость в обоих случаях:
%%time cache_op(200001,200001)
Во втором случае скорость исчисляется в десятках микросекунд, когда в первом - в сотнях миллисекунд. Следовательно, наше кэширование работает.