Say I have a function in Python that uses a constant computed float value like 1/3.
def div_by_3(x):
return x * (1/3)
If I call the function repeatedly, will the value of 1/3 be automatically cached for efficiency? Or do I have to do something manually such as the following?
def div_by_3(x, _ONE_THIRD=1/3):
return x * _ONE_THIRD
No, it's not. The call will be done twice. So, there's room for optimizing the code. – Klaus D.
Caching is an optimization technique that you can use in your applications to keep recent or often-used data in memory locations that are faster or computationally cheaper to access than their source. Imagine you're building a newsreader application that fetches the latest news from different sources.
Find out for yourself! The dis module is great for inspecting this sort of stuff:
>>> from dis import dis
>>> def div_by_3(x):
... return x * (1/3.)
...
>>> dis(div_by_3)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (1)
6 LOAD_CONST 2 (3.0)
9 BINARY_DIVIDE
10 BINARY_MULTIPLY
11 RETURN_VALUE
As you can see, the 1/3
calculation happens every time. (Note: I changed 3
to 3.
to force float division, otherwise it'd just be 0. You can also enable future-division, which actually changed the behavior, see edit section below).
And your second approach:
>>> def db3(x, _ONE_THIRD=1/3.):
... return x * _ONE_THIRD
...
>>> dis(db3)
2 0 LOAD_FAST 0 (x)
3 LOAD_FAST 1 (_ONE_THIRD)
6 BINARY_MULTIPLY
7 RETURN_VALUE
More information on the second can be found by inspecting the function object:
>>> inspect.getargspec(db3)
ArgSpec(args=['x', '_ONE_THIRD'], varargs=None, keywords=None, defaults=(0.3333333333333333,))
You can see the default value is cached in there.
EDIT: Turns out this is a little more interesting -- in Python 3 they do get cached (and also in Python 2.7 when you enable from __future__ import division
):
>>> dis.dis(div_by_3)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 3 (0.3333333333333333)
6 BINARY_MULTIPLY
7 RETURN_VALUE
Switching to integer division (//
) in either Python 3 or 2.7-with-future-division doesn't change this, it just alters the constant to be a 0
instead of 0.333..
Also, using integer division directly in 2.7 without future-division will cache the 0
as well.
Learned something new today!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With