scdmb
scdmb

Reputation: 15641

__globals__ in imported function is much different than __globals__ of function in main module

File a.py:

def f():
  pass

File main.py:

import a
print("f globals")
print(a.f.__globals__)

def g():
  pass

print("g globals")
print(g.__globals__)

a.f.__globals__ have much more elements than g.__globals__. At the first look it seems that built-in functions and types are in a.f.__globals__. Why these two dictionaries are different?

Upvotes: 3

Views: 6939

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124548

You are looking at the module namespaces. The f() globals differs from g() globals because they both live in different modules.

You'll see the same global namespace if you use vars() (for globals in main) and vars(a) (for the globals of module a):

print(sorted(vars(a).keys() - vars()))
# prints ['__initializing__', 'f'], only `a` has `f` defined, the `__initializing__` value is a flag used by the import machinery
print(sorted(vars().keys() - vars(a)))
# prints ['a', 'g'], only `main` has imported `a` and defined function `g`

Each and every module gets its own namespace, globals() are not interpreter global, they are module global only. Importing a module means you are importing a reference to that namespace, or creating references to names in that namespace.

From the datamodel documentation on module objects:

A module object has a namespace implemented by a dictionary object (this is the dictionary referenced by the __globals__ attribute of functions defined in the module)

and on function objects:

__globals__: A reference to the dictionary that holds the function’s global variables — the global namespace of the module in which the function was defined.

The __builtins__ key of the main script merely points to the __builtins__ module, in imported modules that has been expanded into a dictionary. These are the same thing, really.

Upvotes: 4

Related Questions