Ways to make a free variable local to a function?

Kirill Balunov kirillbalunov at gmail.com
Mon Mar 5 07:12:37 EST 2018


Hi,

At the moment, in order to slightly speed up the function in Python, free
variables are passed as local variables to the function, thereby getting
rid of extra look ups. For example, for the following function, I
especially do not use list comprehension) and therefore maybe it's not the
best example:

    def func(numb):
        res = []
        for i in range(numb):
            res.append(int(i) + float(i))
        return res

You can get rid of additional look ups, in the following ways:


# 1. By passing through local variable's default values

    def func_local_1(numb, _int = int, _float = float, _range = range):
    res = []
    for i in _range(numb):
        res.append(_int(i) + _float(i))
    return res


# 2. Through importing them into the function scope

    def func_local_2(numb):
        from builtins import int, float, range
        res = []
        for i in range(numb):
            res.append(int(i) + float(i))
        return res


# 3. With the help of various types of closures, version 1

    def func_closure_1(numb):
        _int = int
        _float = float
        _range = range
        def inner(numb):
            res = []
            for i in _range(numb):
                res.append(_int(i) + _float(i))
            return res
        return inner(numb)


# 4. With the help of various types of closures, version 2

    def func_closure_2(numb):
        from builtins import int, float, range
        def inner(numb):
            res = []
            for i in range(numb):
                res.append(int(i) + float(i))
            return res
        return inner(numb)

Option 1 allows you to achieve the maximum result for both small and a
large `numb` values. Option 2 yields a significant overhead, when it is
required to call function many times with a small number of iterations. For
option 3 and 4, notes are the same, but since they are implemented through
closures they give additional small overhead. In case of big `numb` (many
iterations, many look ups) these options give a gain of ~10%.

Option 1 and 3 I do not like because:
 - syntax highlighting stops working
 - the signature function is greatly distorted
 - additional typing (especially with type annotations)

I like options 2 and 4, but they yield a significant overhead, for a small
number of iterations.

Actually, I have the following question:

1. Is there any other way to make the variable local to the function?
     a. When you compile (define) a function...
     b. Inject into an already existing function through decorator...(is it
possible?)

p.s.:

I had the following idea, maybe it was already discussed, the possibility
of setting _static_ variables for functions, with the following syntax:

    def func(numb):
        static int, float, range
        res = []
        for i in range(numb):
            res.append(int(i) + float(i))
        return res

Where identifiers for `static` should correspond to free variables for a
function, they must be defined at compile time (like for default arguments)
and can not be changed inside the function scope.

With kind regards,
-gdg



More information about the Python-list mailing list