Reason for globals() in Python?
Asked Answered
B

10

71

What is the reason of having globals() function in Python? It only returns dictionary of global variables, which are already global, so they can be used anywhere... I'm asking only out of curiosity, trying to learn python.

def F():
    global x
    x = 1

def G():
    print(globals()["x"]) #will return value of global 'x', which is 1

def H():
    print(x) #will also return value of global 'x', which, also, is 1

F()
G()
H()

I can't really see the point here? Only time I would need it, was if I had local and global variables, with same name for both of them

def F():
    global x
    x = 1

def G():
    x = 5
    print(x) #5
    print(globals()["x"]) #1

F()
G()

But you should never run into a problem of having two variables with same name, and needing to use them both within same scope.

Bayard answered 2/10, 2012 at 15:39 Comment(4)
"But you should never run into a problem of having two variables with same name, and needing to use them both within same scope." I can't follow this thought. That's the whole reason for separate namespaces, that you have variables with the same name in different scopes. When you work with two of them, duplicate names are a natural thing, but not a problem, as you can prefix them.Squiggle
Well I come from C++ family, so I'm not sure about Python people, but as far as I can think of, you shouldn't have a global variable that doesn't have an unique name. Sure there will be variables with same name, in same scope, that was stupid sentence from me, but not globals with same names as local ones. That's when I'd use namespaces for local ones... But don't know, if you say so.Bayard
@Mahi: globals is perhaps a little misleading. globals() is essentially the locals() of a module. The closest Python comes to globals that are truly global to all of your program is the __builtin__ module; anything you add to that module becomes available in all namespaces everywhere.Ertha
Hmm, good addition, not that I would need it right now, but maybe will some day... Thanks :)Bayard
S
93

Python gives the programmer a large number of tools for introspecting the running environment. globals() is just one of those, and it can be very useful in a debugging session to see what objects the global scope actually contains.

The rationale behind it, I'm sure, is the same as that of using locals() to see the variables defined in a function, or using dir to see the contents of a module, or the attributes of an object.

Coming from a C++ background, I can understand that these things seem unnecessary. In a statically linked, statically typed environment, they absolutely would be. In that case, it is known at compile time exactly what variables are global, and what members an object will have, and even what names are exported by another compilation unit.

In a dynamic language, however, these things are not fixed; they can change depending on how code is imported, or even during run time. For that reason at least, having access to this sort of information in a debugger can be invaluable.

Sachs answered 2/10, 2012 at 16:7 Comment(3)
+1. Also, the dictionary returned by globals can be modified (probably a capability best left to experts). Also relevant is this quote from Dive Into Python "Using the locals and globals functions, you can get the value of arbitrary variables dynamically, providing the variable name as a string. This mirrors the functionality of the getattr function, which allows you to access arbitrary functions dynamically by providing the function name as a string."Rosefish
Not saying your answer was any better than other's, but for me it was. Thanks, I guess I need to calm down and remember that Python is not C++ :) And thanks for everyone else answering too, cleared quite alot.Bayard
Changing elements in locals() usually doesn't work. Most python functions don't have a dict for locals - so when you call locals() it constructs a dict of the current values of the locals; changing that dict doesn't reflect to the locals. There were cases where functions did things like "import * from xyz" (no longer allowed) - that sets locals with names unknown at compile time; those functions were compiled with an actual locals dict, Long ago, all functions had an actual locals dict, and they have phasing out the need for that, I don't know under what conditions you have a dict now.Caracole
S
44

It's also useful when you need to call a function using function's string name. For example:

def foo():
    pass

function_name_as_string = 'foo'

globals()[function_name_as_string]() # foo(). 
Salimeter answered 23/9, 2013 at 17:46 Comment(2)
What if the function has many parameters like, def foo(a, b, c=false). How would you pass those parameters to globals()Gmur
@ksooklall You pass it to the function as usual: with def foo(*args): print("hw", *args) you can do: globals()['foo']() or globals()['foo']('reason', 42) etc.Rustyrut
H
8

You can pass the result of globals() and locals() to the eval, execfile and __import__ commands. Doing so creates a restricted environment for those commands to work in.

Thus, these functions exist to support other functions that benefit from being given an environment potentially different from the current context. You could, for example, call globals() then remove or add some variables before calling one of those functions.

Huffish answered 2/10, 2012 at 16:11 Comment(0)
M
6

globals() is useful for eval() -- if you want to evaluate some code that refers to variables in scope, those variables will either be in globals or locals.


To expand a bit, the eval() builtin function will interpret a string of Python code given to it. The signature is: eval(codeString, globals, locals), and you would use it like so:

def foo():
    x = 2
    y = eval("x + 1", globals(), locals())
    print("y=" + y) # should be 3

This works, because the interpreter gets the value of x from the locals() dict of variables. You can of course supply your own dict of variables to eval.

Misdeal answered 2/10, 2012 at 15:47 Comment(5)
I wasn't the one downvoting, but that didn't really make sense, could you give an example code for easier understanding?Bayard
Sure, I've expanded my answer.Misdeal
Kinda weird and seems useless for me, but maybe that's just cause I'm new to Python :P Thanks anywaysBayard
eval("x+1") does the same thing, due to its default parameters; see help(eval)Caracole
Have a look also here with how globals() can be used: https://mcmap.net/q/49811/-convert-string-into-a-function-call.Otalgia
C
1

It can be useful in 'declarative python'. For instance, in the below FooDef and BarDef are classes used to define a series of data structures which are then used by some package as its input, or its configuration. This allows you a lot of flexibility in what your input is, and you don't need to write a parser.

# FooDef, BarDef are classes

Foo_one = FooDef("This one", opt1 = False, valence = 3 )
Foo_two = FooDef("The other one", valence = 6, parent = Foo_one )

namelist = []
for i in range(6):
    namelist.append("nm%03d"%i)

Foo_other = FooDef("a third one", string_list = namelist )

Bar_thing = BarDef( (Foo_one, Foo_two), method = 'depth-first')

Note that this configuration file uses a loop to build up a list of names which are part of the configuration of Foo_other. So, this configuration language comes with a very powerful 'preprocessor', with an available run-time library. In case you want to, say, find a complex log, or extract things from a zip file and base64 decode them, as part of generating your configuration (this approach is not recommended, of course, for cases where the input may be from an untrusted source...)

The package reads the configuration using something like the following:

conf_globals = {}  # make a namespace
# Give the config file the classes it needs
conf_globals['FooDef']= mypkgconfig.FooDef  # both of these are based ...
conf_globals['BarDef']= mypkgconfig.BarDef  # ... on .DefBase

fname = "user.conf"
try:
    exec open(fname) in conf_globals
except Exception:
    ...as needed...
# now find all the definitions in there
# (I'm assuming the names they are defined with are
# significant to interpreting the data; so they
# are stored under those keys here).

defs = {}
for nm,val in conf_globals.items():
    if isinstance(val,mypkgconfig.DefBase):
        defs[nm] = val

So, finally getting to the point, globals() is useful, when using such a package, if you want to mint a series of definitions procedurally:

for idx in range(20):
    varname = "Foo_%02d" % i
    globals()[varname]= FooDef("one of several", id_code = i+1, scale_ratio = 2**i)

This is equivalent to writing out

Foo_00 = FooDef("one of several", id_code = 1, scale_ratio=1)
Foo_01 = FooDef("one of several", id_code = 2, scale_ratio=2)
Foo_02 = FooDef("one of several", id_code = 3, scale_ratio=4)
... 17 more ...

An example of a package which obtains its input by gathering a bunch of definitions from a python module is PLY (Python-lex-yacc) http://www.dabeaz.com/ply/ -- in that case the objects are mostly function objects, but metadata from the function objects (their names, docstrings, and order of definition) also form part of the input. It's not such a good example for use of globals() . Also, it is imported by the 'configuration' - the latter being a normal python script -- rather than the other way around.

I've used 'declarative python' on a few projects I've worked on, and have had occasion to use globals() when writing configurations for those. You could certainly argue that this was due to a weakness in the way the configuration 'language' was designed. Use of globals() in this way doesn't produce very clear results; just results which might be easier to maintain than writing out a dozen nearly-identical statements.

You can also use it to give variables significance within the configuration file, according to their names:

# All variables above here starting with Foo_k_ are collected
# in Bar_klist
#
foo_k = [ v for k,v in globals().items() if k.startswith('Foo_k_')]
Bar_klist  = BarDef( foo_k , method = "kset")

This method could be useful for any python module that defines a lot of tables and structures, to make it easier to add items to the data, without having to maintain the references as well.

Caracole answered 20/6, 2015 at 23:34 Comment(0)
V
1

It might be useful if you like to import module you just have built:

a.py

[...]

def buildModule():
    [...code to build module...]
    return __import__("somemodule")

[...]

b.py

from a import buildModule

def setup():
   globals()["somemodule"] = buildModule()
Vorous answered 15/11, 2019 at 13:38 Comment(0)
G
0

It can also be used to get an instance of the class 'classname' from a string:

class C:
    def __init__(self, x):
        self.x = x
        print('Added new instance, x:', self.x)


def call(str):
    obj = globals()[str](4)
    return obj

c = call('C')
print(c.x)
Gaming answered 30/3, 2018 at 13:34 Comment(0)
G
0

Not really. Global variables Python really has are module-scoped variables.

# a.py
print(globals())

import b
b.tt()
# b.py
def tt():
    print(globals())

run python a.py, at least two output of globals()['__name__'] is different.

Code here in cpython on Github shows it.

Gaunt answered 5/3, 2020 at 9:18 Comment(0)
P
0

I did not notice in answers anything about using globals() to check if you have value set. Maybe you only set value if debugging or have forgotten to set one and want to avoid getting exception. Though locals() might be better solution in some of the cases to avoid accessing global scope and to access local scope only.

# DEBUG = True
if 'DEBUG' in globals():
    print(f'We found debug flag and it has value {DEBUG}.')
else: 
    print(f'Debug flag was not found.')

Also you can use it with combination with get() to set the default value in case variable was not found

# VARIABLE = "Value of var"
my_var = globals().get("VARIABLE", "Value was not found")
print(my_var)    # Prints: "Value was not found"
print(VARIABLE)  # Raises NameError

VARIABLE = "Value of var"
my_var = globals().get("VARIABLE", "Value was not found")
print(my_var)    # prints: "Value of var"
print(VARIABLE)  # prints: "Value of var"
Penetrating answered 29/3, 2021 at 14:28 Comment(0)
S
0

It allows you, among other things, to access, call, (re)define global variables in the current module scope, by looking them up in the dictionary that stores them.

For example, you might need to call several functions that have names like func1, func2, func3 and so on. Instead of manually typing them, one way is to iterate over globals() by passing the string f'func_{i}', in a for loop:

def func1():
    return 1

def func2():
    return 2

def func3():
    return 3

for i in range(1, 4):
    print(globals()[f'func{i}']())

See an example of this here (bottom cell)

Strumpet answered 31/3, 2023 at 9:44 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.