2

The fact the global variables in python are slower than local ones is pretty well known and has already been discussed in different questions in this site. However, one thing I still haven't found an answer for is, what's the best and fastest way to use global variables (like constant, a concept that doesn't exist in python) that are used inside different functions in the code?

The best solution I could find so far is to define a closure function where I assign the global variable to the local one.

from timeit import timeit

number = 10

def flocal():
    number = 10
    for i in range(25):
        x = number

def fglobal():
    for i in range(25):
        x = number

def fglobal_wrapper():
    global_number = number
    def actual_func():
        for i in range(25):
            x = global_number
    return actual_func

fclosure = fglobal_wrapper()

print("local: %.3f" % timeit("flocal()", "from __main__ import flocal"))
print("global: %.3f" % timeit("fglobal()", "from __main__ import fglobal"))
print("closure: %.3f" % timeit("fclosure()", "from __main__ import fclosure"))

Output:

local: 0.681
global: 0.806
closure: 0.728

But that's an ugly solution, and it's still slower then using a local variable. What is the best known method to use a global/constant variable equivalent inside functions, without having to use pass them as arguments to the function, or this closure workaround?

martineau
  • 119,623
  • 25
  • 170
  • 301
aviro
  • 184
  • 9

1 Answers1

1
def fglobal2():
    global_number = number # single access to global
    for i in range(25):
        x = global_number

is as fast as local on my machine (I run 10x more tests for less noise in time estimation)

local: 4.409
global: 4.914
global2: 4.406  # proposed, as fast as local
closure: 4.560
lejlot
  • 64,777
  • 8
  • 131
  • 164
  • adding on a bit more detail (which this answer doesn't clarify), but the only difference between this version and `fglobal_wrapper` is that the original version creates and returns a new func; since global_number is actually in the closure as opposed to within the function locals in that case, it runs slower in timeit. In this approach, global_number is explicitly in function `locals()`, so it runs a bit faster because python already finds it when it checks the function locals, so it doesn't need to check other scopes, like closures and globals to find `global_number`. Hope this helps. – rv.kvetch Nov 22 '21 at 18:33