Ways to make a free variable local to a function?
Terry Reedy
tjreedy at udel.edu
Mon Mar 5 08:52:40 EST 2018
On 3/5/2018 7:12 AM, Kirill Balunov wrote:
> 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):
You are not required to mangle the names.
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
Only because you unnecessarily mangle the names.
> - 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
>
--
Terry Jan Reedy
More information about the Python-list
mailing list