2

From the below program, I understand that local frame(square)(blue colour box) in the below Environment diagram belongs to(nothing but), the local ACTIVATION RECORD of call() method of an object of class 'function'. This 'function' class object is created internally when we defined function square(x).

enter image description here

My question is:

If my understanding is correct above, then to whom(which class object's method) does global frame belong to?

Because, I feel, the control has been passed from some method of an object(particular class type) to square.call(3) method.

overexchange
  • 15,768
  • 30
  • 152
  • 347

1 Answers1

2

When a function is defined, it's assigned the read-only attribute func_globals (a.k.a. __globals__ since 2.6 and only that since 3.0) which corresponds to the current module namespace (like a view to the module.__dict__). You can try, for example:

>>> square.func_globals
# get a big dictionary-like object here

This object is queried every time the function accesses a global variable. When you later import this function in some other module, it will still keep the reference to its original scope and will take the globals from there. In other words, the code:

def square(x):
    return mul(x, x)

is roughly the same as:

def square(x):
    return globals()['mul'](x, x)

or

def square(x):
    return square.func_globals['mul'](x, x)

So, in one sentence: function's globals belong to the module where it is defined, and accessed through the function object's attributes.

UPDATE

More elaborated version of what happens underneath (applies to CPython). The most important thing to understand about Python is, that, unlike C etc, it has no clear separation between "declaration" and "execution". When you load a module, its code is simply executed. When the interpreter comes across a function definition, it creates the function object and assigns it to the variable. Whatever has been defined or imported into the module will become available to the function as global variables. Lets have a look at the function object:

>>> import dis
>>> dis.dis(square.func_code)  # disassemble the function's bytecode
2           0 LOAD_GLOBAL              0 (mul)
            3 LOAD_FAST                0 (x)
            6 LOAD_FAST                0 (x)
            9 CALL_FUNCTION            2
           12 RETURN_VALUE        
>>> square.func_code.co_names
('mul',)

You can see the code LOAD_GLOBAL 0 in the beginning. That means:

  1. find the name with the index 0 in co_names, which is 'mul'
  2. find the name 'mul' in func_globals and load it to the stack
  3. do the rest of the logic
bereal
  • 32,519
  • 6
  • 58
  • 104
  • bereal In you statement: "function's global are the modules name space" ---- I did not understand the meaning of 'modules namespace'. -----As of now what i know is 'operator' is a reference variable pointing to an object(say OBJ)(of class 'module') and 'mul' is a reference variable pointing to one member object(of class 'function') in that OBJ(of class 'module'). So, Which module are talking about? – overexchange Mar 30 '14 at 10:21
  • @Sham When you say `from operator import mul`, that `mul` is added to the _current_ module's namespace. When you define a function inside that module, it also has access to that namespace through `func_globals`. So, I'm talking about the module, where the function is defined. When you later import that function to another module, it still keeps reference to its original scope. Updated the answer. – bereal Mar 30 '14 at 10:24
  • bereal i would like to chat with you, i am not able to understand meaning 'current module's namespace'. you are saying about the module where the function is defined. But am not clear about concept of current module and namespace? can i chat with u? – overexchange Mar 30 '14 at 13:55
  • >>> from operator import mul >>> def square(x): return mul(x,x) >>> square.__globals__ {'square': , '__builtins__': , '__package__': None, 'mul': , '__name__': '__main__', '__doc__': None} >>> i was unable to inperpret the square.__globals__ output, What is it talking about? – overexchange Mar 30 '14 at 14:05
  • `square.__globals__` contains the globals the function `square` has access to. That means, every time the bytecode interpreter comes across `LOAD_GLOBAL`, it will explore this dictionary to find the corresponding variable, and will raise `NameError` if it fails to do so. Will try to update the answer, will continue in chat if it does not help. – bereal Mar 30 '14 at 14:12
  • bereal So, global frame box diagram that i see above is nothing but 'current module's namespace'. and later when i defined the function square in that module's namespace and use mul within it, square will search mul object in func_globals member object of square using LOAD_GLOBAL instruction in its bytecode. But what is this term 'current module's namespace'? when does this come into existence? can we chat further? am not getting this statement: 'which corresponds to the current module namespace (like a view to the module.__dict__)' – overexchange Mar 30 '14 at 22:35
  • @Sham By current module I mean, the module where the function is defined, and the one you're looking at while debugging the function. It comes into existence when the module is imported for the first time and then populated with whatever is defined in the module (imports, global variables, functions, classes). – bereal Mar 31 '14 at 06:17
  • bereal Oh When you say current module, it is the module in which this code: 'from operator import mul def...urn mul(x,x) square.__call__(3)' is written? so you call this as module? Are you talking about 'Dictionaries on dictionaries. Dictionaries are the number 1 most important structure in Python as per [link](http://stackoverflow.com/questions/22604974/python-memory-model-for-this-program) how can i visualise this module structure? like i can visualise my defined function using square.() and see the output and what is namespace? – overexchange Mar 31 '14 at 11:27
  • @Sham Sorry, now I don't understand completely... Modules are just yet another kind of objects, as everything in Python, and as any object, they're build on top of dictionaries. So if you want introspection, access `module.__dict__`. That will return you what any function in that module sees as its "global frame". – bereal Mar 31 '14 at 11:39
  • bereal as you said before to try module.__dict__ i get this output----Python 3.2.3 ......information. >>> module.__dict__ Traceback (most recent call last): File "", line 1, in module.__dict__ NameError: name 'module' is not defined >>> operator.__dict__ Traceback (most recent call last): File "", line 1, in operator.__dict__ NameError: name 'operator' is not defined >>> – overexchange Mar 31 '14 at 13:33
  • bereal ya i now see all the functions, but when you say 'import operator'? in to what did we import? can we chat further? – overexchange Mar 31 '14 at 13:46
  • @Sham ok, create a chat and invite me. – bereal Mar 31 '14 at 13:47
  • bereal i dont know how to create chat, sorry about that, can u please do that? i never did this before – overexchange Mar 31 '14 at 13:48
  • bereal can u some back for 5 mins for chat? – overexchange Mar 31 '14 at 14:48