Pregunta

I've come across recently a number of places in our code which do things like this

...
globals()['machine'] = otherlib.Machine()
globals()['logger'] = otherlib.getLogger()
globals()['logfile'] = datetime.datetime.now().strftim('logfiles_%Y_%m_%d.log')

and I am more than a little confused as to why people would do that, rather than doing

global machine
machine = otherlib.Machine()

and so on.

Here is a slightly anonymised function which does this, in full:

def openlog(num)
    log_file = '/log_dir/thisprogram.' + num
    if os.path.exists(log_file):
        os.rename(log_file, log_file + '.old')

    try:
        globals()["log"] = open(log_file, 'w')
        return log
    except:
       print 'Unable to open ' + log_file
       sys.exit(1)

It confuses the hell out of pylint (0.25) as well me.

Is there any reason for coding it that way? There's minimal usage of eval in our code, and this isn't in a library

PS I checked Reason for globals() in python but it doesn't really answer as to why you'd use this for setting globals in a program

¿Fue útil?

Solución

Maybe the function uses a local variable with the same name as the global one, and the programmer didn't want to bother changing the variable name?

def foo(bar):
    global bar # SyntaxError
    bar = bar + 1

def foo(bar):
    globals()['bar'] = bar + 1 
foo(1)
print(bar) # prints 2

Another use case, albeit still a bit specious (and clearly not the case in the example function you gave), is for defining variable names dynamically. This is rarely, if ever, a good idea, but it does come up a lot in questions on this site, at least. For example:

>>> def new_variable():
...     name = input("Give your new variable a name! ")
...     value = input("Give your new variable a value! ")
...     globals()[name] = value
...
>>> new_variable()
Give your new variable a name! foo
Give your new variable a value! bar
>>> print(foo)
bar

Otherwise, I can think of only one reason to do this: perhaps some supervising entity requires that all global variables be set this way, e.g. "in order to make it really, really clear that these variables are global". Or maybe that same supervising entity has placed a blanket ban on the global keyword, or docks programmer pay for each line.

I'm not saying that any of these would be a good reason, but then again, I truly can't conceive of a good reason to define variables this way if not for scoping purposes (and even then, it seems questionable...).


Just in case, I did a timing check, to see if maybe the globals() call is faster than using the keyword. I'd expect the function call + dictionary access to be significantly slower, and it is.

>>> import timeit
>>> timeit.timeit('foo()', 'def foo():\n\tglobals()["bar"] = 1',number=10000000)
2.733132876863408
>>> timeit.timeit('foo()', 'def foo():\n\tglobal bar\n\tbar = 1',number=10000000)
1.6613818077011615

Given the code you posted and my timing results, I can think of no legitimate reason for the code you're looking at to be written like this. Looks like either misguided management requirement, or simple incompetence.

Otros consejos

Are the authors PHP converts? This is a valid code in PHP:

$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];

See this for more examples. If someone was used to this way of writing the code, maybe they just used the closest matching way of doing it in Python and didn't bother to check for alternatives.

You'd sometimes use a superglobal $GLOBAL variable to define something, because although global keyword exists in PHP, it will only import existing variables - it cannot create a new variable as far as I know.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top