Alex Kosh
Alex Kosh

Reputation: 2554

Is it more performant to access function from variable?

I was reading sources of Python statistics module and saw strage variable partials_get = partials.get which then was used once in for loop partials[d] = partials_get(d, 0) + n.

def _sum(data, start=0):
    count = 0
    n, d = _exact_ratio(start)
    partials = {d: n}
    partials_get = partials.get  # STRANGE VARIABLE
    T = _coerce(int, type(start))
    for typ, values in groupby(data, type):
        T = _coerce(T, typ)  # or raise TypeError
        for n, d in map(_exact_ratio, values):
            count += 1
            partials[d] = partials_get(d, 0) + n  # AND IT'S USAGE
    if None in partials:
        # The sum will be a NAN or INF. We can ignore all the finite
        # partials, and just look at this special one.
        total = partials[None]
        assert not _isfinite(total)
    else:
        # Sum all the partial sums using builtin sum.
        # FIXME is this faster if we sum them in order of the denominator?
        total = sum(Fraction(n, d) for d, n in sorted(partials.items()))
    return (T, total, count)

So my question: Why not just write partials[d] = partials.get(d, 0) + n? Is it slower than storing and calling function from variable?

Upvotes: 0

Views: 61

Answers (2)

Barmar
Barmar

Reputation: 780724

partials.get has to search for the get attribute, starting with the object's dictionary and then going to the dictionary of the class and its parent classes. This will be done each time through the loop.

Assigning it to a variable does this lookup once, rather than repeating it.

This is a microoptimization that's typically only significant if the loop has many repetitions. The statistics library often processes large data sets, so it's reasonable here. It's rarely needed in ordinary application code.

Upvotes: 3

Cireo
Cireo

Reputation: 4427

Short answer: yes.

Python is an interpreted language, and while dictionary/attribute access is blazingly fast and very optimized, it still incurs a hit.

Since they are running this in a tight loop, they are taking the slight performance advantage of removing the "dot" from accessing partials.get.

There are other slight improvements from doing this in other cases where the variable is enough of a hint to the compiler (for cpython at least) to ensure this stays local, but I'm not sure this is the case here.

Upvotes: 2

Related Questions